home *** CD-ROM | disk | FTP | other *** search
- //-----------------------------------------------------------------------------
- // File: Donuts.cpp
- //
- // Desc: DirectInput semantic mapper version of Donuts3D game
- //
- // Copyright (C) 1995-2000 Microsoft Corporation. All Rights Reserved.
- //-----------------------------------------------------------------------------
- #define STRICT
- #include <windows.h>
- #include <windowsx.h>
- #include <basetsd.h>
- #include <cguid.h>
- #include <tchar.h>
- #include <mmsystem.h>
- #include <stdio.h>
- #include <math.h>
- #include <D3DX8.h>
- #include "D3DFile.h"
- #include "D3DFont.h"
- #include "D3DUtil.h"
- #include "DIUtil.h"
- #include "DMUtil.h"
- #include "DXUtil.h"
- #include "resource.h"
- #include "donuts.h"
- #include "gamemenu.h"
-
-
-
-
- //-----------------------------------------------------------------------------
- // Custom Direct3D vertex types
- //-----------------------------------------------------------------------------
- struct SCREENVERTEX
- {
- D3DXVECTOR4 p;
- DWORD color;
- };
-
- struct SPRITEVERTEX
- {
- D3DXVECTOR3 p;
- DWORD color;
- FLOAT tu, tv;
- };
-
- struct MODELVERTEX
- {
- D3DXVECTOR3 p;
- D3DXVECTOR3 n;
- FLOAT tu, tv;
- };
-
- #define D3DFVF_SCREENVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)
- #define D3DFVF_SPRITEVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
- #define D3DFVF_MODELVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1)
-
-
-
-
- //-----------------------------------------------------------------------------
- // Application globals
- //-----------------------------------------------------------------------------
- TCHAR* g_strAppName = _T("Donuts3D");
- GUID g_AppGuid = { 0x451F8CCC, 0xA7E9, 0x4DF4, 0x9A, 0x6B,
- 0xF4, 0xA7,0xC7, 0x06, 0xF3, 0x33 };
-
- HWND g_hWndMain; // Main window
- DWORD g_dwScreenWidth = 800; // Dimensions for fullscreen modes
- DWORD g_dwScreenHeight = 600;
- D3DDISPLAYMODE g_DesktopMode;
- D3DFORMAT g_d3dfmtFullscreen; // Pixel format for fullscreen modes
- D3DFORMAT g_d3dfmtTexture; // Pixel format for textures
- BOOL g_bFullScreen = FALSE; // Whether app is fullscreen (or windowed)
- BOOL g_bIsActive; // Whether app is active
- BOOL g_bDisplayReady = FALSE; // Whether display class is initialized
- BOOL g_bMouseVisible = TRUE; // Whether mouse is visible
- HBITMAP g_hSplashBitmap = NULL; // Bitmap for splash screen
-
- DWORD g_dwAppState; // Current state the app is in
- DWORD g_dwLevel = 0; // Current game level
- DWORD g_dwScore = 0; // Current game score
-
- // Player view mode
- #define NUMVIEWMODES 3
- CD3DCamera g_Camera; // Camera used for 3D scene
- DWORD g_dwViewMode = 0; // Which view mode is being used
- FLOAT g_fViewTransition = 0.0f; // Amount used to transittion views
- BOOL g_bAnimatingViewChange = FALSE; // Whether view is transitioning
- BOOL g_bFirstPersonView = TRUE; // Whether view is first-person
-
- // Bullet mode
- FLOAT g_fBulletRechargeTime = 0.0f; // Recharge time for firing bullets
- DWORD g_dwBulletType = 0L; // Current bullet type
-
- // Display list and player ship
- DisplayObject* g_pDisplayList = NULL; // Global display list
- CShip* g_pShip = NULL; // Player's display object
-
- // DirectDraw/Direct3D objects
- LPDIRECT3DDEVICE8 g_pd3dDevice = NULL; // Class to handle D3D device
- D3DPRESENT_PARAMETERS g_d3dpp;
- LPDIRECT3DSURFACE8 g_pConfigSurface = NULL; // Surface for config'ing DInput devices
- LPDIRECT3DVERTEXBUFFER8 g_pViewportVB = NULL;
- LPDIRECT3DVERTEXBUFFER8 g_pSpriteVB = NULL;
-
- // Support for the ship model
- CD3DMesh* g_pShipFileObject = NULL; // Geometry model of player's ship
- DWORD g_dwNumShipTypes = 10L;
- DWORD g_dwCurrentShipType = 0L;
- TCHAR* g_strShipFiles[] = { _T("Concept Plane 3.x"), _T("Spaceship 2.x"), _T("Shusui.x"),
- _T("Space Station 7.x"), _T("Spaceship 8.x"), _T("Orbiter.x"),
- _T("Spaceship 13.x"), _T("Spaceship 5.x"), _T("Star Sail.x"),
- _T("Heli.x"), };
- TCHAR* g_strShipNames[] = { _T("Concept Plane"), _T("Green Machine"), _T("Purple Prowler"),
- _T("Drone Clone"), _T("Canyon Fighter"), _T("Roundabout"),
- _T("Tie-X7"), _T("Gunner"), _T("Star Sail"),
- _T("Helicopter"), };
-
- // DirectMusic objects
- CMusicManager* g_pMusicManager = NULL; // Class to manage DMusic objects
- CMusicSegment* g_pBeginLevelSound = NULL; // Sounds for the app
- CMusicSegment* g_pEngineIdleSound = NULL;
- CMusicSegment* g_pEngineRevSound = NULL;
- CMusicSegment* g_pShieldBuzzSound = NULL;
- CMusicSegment* g_pShipExplodeSound = NULL;
- CMusicSegment* g_pFireBulletSound = NULL;
- CMusicSegment* g_pShipBounceSound = NULL;
- CMusicSegment* g_pDonutExplodeSound = NULL;
- CMusicSegment* g_pPyramidExplodeSound = NULL;
- CMusicSegment* g_pCubeExplodeSound = NULL;
- CMusicSegment* g_pSphereExplodeSound = NULL;
-
- // Game objects
- LPDIRECT3DTEXTURE8 g_pGameTexture1 = NULL; // Texture with game object animations
- LPDIRECT3DTEXTURE8 g_pGameTexture2 = NULL; // Texture with game object animations
- CD3DMesh* g_pTerrain = NULL; // Geometry model of terrain
- CD3DFont* g_pGameFont = NULL; // Font for displaying score, etc.
- CD3DFont* g_pMenuFont = NULL; // Font for displaying in-game menus
-
-
- // Menu objects
- CMenuItem* g_pMainMenu = NULL; // Menu class for in-game menus
- CMenuItem* g_pQuitMenu = NULL;
- CMenuItem* g_pCurrentMenu = NULL;
-
- // Defines for the in-game menu
- #define MENU_MAIN 1
- #define MENU_SOUND 2
- #define MENU_VIDEO 3
- #define MENU_INPUT 4
- #define MENU_VIEWDEVICES 5
- #define MENU_CONFIGDEVICES 6
- #define MENU_WINDOWED 7
- #define MENU_640x480 8
- #define MENU_800x600 9
- #define MENU_1024x768 10
- #define MENU_BACK 11
- #define MENU_SOUNDON 12
- #define MENU_SOUNDOFF 13
- #define MENU_QUIT 14
-
-
- // DirectInput objects
- CInputDeviceManager* g_pInputDeviceManager = NULL; // Class for managing DInput devices
- DIACTIONFORMAT g_diafGame; // Action format for game play
- DIACTIONFORMAT g_diafBrowser; // Action format for menu navigation
-
- // Game input variables
- FLOAT g_fBank = 0.0f;
- FLOAT g_fThrust = 0.0f;
- BOOL g_bFiringWeapons = FALSE;
- BOOL g_bChangeView = FALSE;
- BOOL g_bPaused = FALSE;
-
- // Menu input variables
- BOOL g_bMenuLeft = FALSE;
- BOOL g_bMenuRight = FALSE;
- BOOL g_bMenuUp = FALSE;
- BOOL g_bMenuDown = FALSE;
- BOOL g_bMenuSelect = FALSE;
- BOOL g_bMenuQuit = FALSE;
-
-
- //-----------------------------------------------------------------------------
- // Game actions (using DInput semantic mapper). The definitions here are kind
- // of the whole point of this sample. The game uses these actions to map
- // physical input like, "the user pressed the 'W' key", to a more useable
- // constant for the game, like "if( dwInput == INPUT_CHANGEWEAPONS )...".
- //-----------------------------------------------------------------------------
-
-
- // Input semantics used by this game
- enum INPUT_SEMANTICS
- {
- // Gameplay semantics
- INPUT_AXIS_LR=1, INPUT_AXIS_UD, INPUT_AXIS_SHIPTYPE,
- INPUT_MOUSE_LR, INPUT_MOUSE_UD, INPUT_MOUSE_SHIPTYPE,
- INPUT_TURNLEFT, INPUT_TURNRIGHT, INPUT_FORWARDTHRUST,
- INPUT_REVERSETHRUST, INPUT_FIREWEAPONS, INPUT_CHANGESHIPTYPE,
- INPUT_CHANGEVIEW, INPUT_CHANGEWEAPONS, INPUT_DISPLAYGAMEMENU,
- INPUT_QUITGAME, INPUT_START,
-
- // Menu semantics
- INPUT_MENU_LR, INPUT_MENU_UD, INPUT_MENU_WHEEL,
- INPUT_MENU_UP, INPUT_MENU_DOWN, INPUT_MENU_LEFT,
- INPUT_MENU_RIGHT, INPUT_MENU_SELECT, INPUT_MENU_QUIT,
- };
-
- // Game actions used by this game.
- DIACTION g_rgGameAction[] =
- {
- { INPUT_AXIS_LR, DIAXIS_SPACESIM_LATERAL, 0, TEXT("Turn"), },
- { INPUT_AXIS_UD, DIAXIS_SPACESIM_MOVE, 0, TEXT("Move"), },
- { INPUT_FIREWEAPONS, DIBUTTON_SPACESIM_FIRE, 0, TEXT("Fire weapons"), },
- { INPUT_CHANGEVIEW, DIBUTTON_SPACESIM_VIEW, 0, TEXT("Change view"), },
- { INPUT_CHANGEWEAPONS, DIBUTTON_SPACESIM_WEAPONS, 0, TEXT("Change weapons"), },
- { INPUT_CHANGESHIPTYPE, DIBUTTON_SPACESIM_LOWER, 0, TEXT("Change ship type"), },
- { INPUT_DISPLAYGAMEMENU, DIBUTTON_SPACESIM_DEVICE, 0, TEXT("Display game menu"), },
- { INPUT_START, DIBUTTON_SPACESIM_MENU, 0, TEXT("Start/pause"), },
-
- { INPUT_TURNLEFT, DIKEYBOARD_LEFT, 0, TEXT("Turn left"), },
- { INPUT_TURNRIGHT, DIKEYBOARD_RIGHT, 0, TEXT("Turn right"), },
- { INPUT_FORWARDTHRUST, DIKEYBOARD_UP, 0, TEXT("Forward thrust"), },
- { INPUT_REVERSETHRUST, DIKEYBOARD_DOWN, 0, TEXT("Reverse thrust"), },
- { INPUT_FIREWEAPONS, DIKEYBOARD_SPACE, 0, TEXT("Fire weapons"), },
- { INPUT_CHANGESHIPTYPE, DIKEYBOARD_A, 0, TEXT("Change ship type"), },
- { INPUT_CHANGEVIEW, DIKEYBOARD_V, 0, TEXT("Change view"), },
- { INPUT_CHANGEWEAPONS, DIKEYBOARD_W, 0, TEXT("Change weapons"), },
- { INPUT_DISPLAYGAMEMENU, DIKEYBOARD_F1, DIA_APPFIXED, TEXT("Display game menu"), },
- { INPUT_START, DIKEYBOARD_PAUSE, 0, TEXT("Start/pause"), },
- { INPUT_QUITGAME, DIKEYBOARD_ESCAPE, DIA_APPFIXED, TEXT("Quit game"), },
-
- { INPUT_MOUSE_LR, DIMOUSE_XAXIS, 0, TEXT("Turn"), },
- { INPUT_MOUSE_UD, DIMOUSE_YAXIS, 0, TEXT("Move"), },
- { INPUT_MOUSE_SHIPTYPE, DIMOUSE_WHEEL, 0, TEXT("Change ship type"), },
- { INPUT_FIREWEAPONS, DIMOUSE_BUTTON0, 0, TEXT("Fire weapons"), },
- { INPUT_CHANGEWEAPONS, DIMOUSE_BUTTON1, 0, TEXT("Change weapons"), },
- };
-
- // Game actions used by this game.
- DIACTION g_rgBrowserAction[] =
- {
- { INPUT_MENU_LR, DIAXIS_BROWSER_LATERAL, 0, TEXT("Left/right"), },
- { INPUT_MENU_UD, DIAXIS_BROWSER_MOVE, 0, TEXT("Up/down"), },
- { INPUT_MENU_SELECT, DIBUTTON_BROWSER_SELECT, 0, TEXT("Select"), },
- { INPUT_MENU_UP, DIBUTTON_BROWSER_PREVIOUS, 0, TEXT("Up"), },
- { INPUT_MENU_DOWN, DIBUTTON_BROWSER_NEXT, 0, TEXT("Down"), },
- { INPUT_MENU_QUIT, DIBUTTON_BROWSER_DEVICE, 0, TEXT("Quit menu"), },
-
- { INPUT_MENU_LEFT, DIKEYBOARD_LEFT, 0, TEXT("Left"), },
- { INPUT_MENU_RIGHT, DIKEYBOARD_RIGHT, 0, TEXT("Right"), },
- { INPUT_MENU_UP, DIKEYBOARD_UP, 0, TEXT("Up"), },
- { INPUT_MENU_DOWN, DIKEYBOARD_DOWN, 0, TEXT("Down"), },
- { INPUT_MENU_SELECT, DIKEYBOARD_SPACE, 0, TEXT("Select"), },
- { INPUT_MENU_SELECT, DIKEYBOARD_RETURN, 0, TEXT("Select"), },
- { INPUT_MENU_SELECT, DIKEYBOARD_NUMPADENTER, 0, TEXT("Select"), },
- { INPUT_MENU_QUIT, DIKEYBOARD_ESCAPE, 0, TEXT("Quit menu"), },
-
- { INPUT_MENU_WHEEL, DIMOUSE_WHEEL, 0, TEXT("Up/down"), },
- { INPUT_MENU_SELECT, DIMOUSE_BUTTON0, 0, TEXT("Select"), },
- };
-
- // Number of actions
- #define NUMBER_OF_GAMEACTIONS (sizeof(g_rgGameAction)/sizeof(DIACTION))
- #define NUMBER_OF_BROWSERACTIONS (sizeof(g_rgBrowserAction)/sizeof(DIACTION))
-
-
-
-
- //-----------------------------------------------------------------------------
- // Inline helper functions
- //-----------------------------------------------------------------------------
-
- // Simple function to define "hilliness" for terrain
- inline FLOAT HeightField( FLOAT x, FLOAT z )
- {
- return (cosf(x/2.0f+0.2f)*cosf(z/1.5f-0.2f)+1.0f) - 2.0f;
- }
-
- // Simple function for generating random numbers
- inline FLOAT rnd( FLOAT low, FLOAT high )
- {
- return low + ( high - low ) * ( (FLOAT)rand() ) / RAND_MAX;
- }
-
- // Convenient macros for playing sounds
- inline VOID PlaySound( CMusicSegment* pSound )
- {
- if( pSound ) pSound->Play( DMUS_SEGF_SECONDARY );
- }
-
- inline VOID StopSound( CMusicSegment* pSound )
- {
- if( pSound ) pSound->Stop();
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: WinMain()
- // Desc: Application entry point
- //-----------------------------------------------------------------------------
- int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow )
- {
- // Register the window class
- WNDCLASS wndClass = { CS_DBLCLKS, WndProc, 0, 0, hInstance,
- LoadIcon( hInstance, MAKEINTRESOURCE(DONUTS_ICON) ),
- LoadCursor( NULL, IDC_ARROW ),
- (HBRUSH)GetStockObject( BLACK_BRUSH ),
- NULL, TEXT("DonutsClass") };
- RegisterClass( &wndClass );
-
- // Create our main window
- g_hWndMain = CreateWindowEx( 0, TEXT("DonutsClass"), TEXT("Donuts"),
- WS_VISIBLE|WS_POPUP|WS_CAPTION|WS_SYSMENU,
- 0, 0, 640, 480, NULL, NULL,
- hInstance, NULL );
- if( NULL == g_hWndMain )
- return FALSE;
- UpdateWindow( g_hWndMain );
-
- // Create the game objects (display objects, sounds, input devices,
- // menus, etc.)
- if( FAILED( CreateGameObjects( g_hWndMain ) ) )
- {
- DestroyWindow( g_hWndMain );
- return FALSE;
- }
-
- // Load keyboard accelerators
- HACCEL hAccel = LoadAccelerators( NULL, MAKEINTRESOURCE(IDR_MAIN_ACCEL) );
-
- // Now we're ready to recieve and process Windows messages.
- BOOL bGotMsg;
- MSG msg;
- PeekMessage( &msg, NULL, 0U, 0U, PM_NOREMOVE );
-
- while( WM_QUIT != msg.message )
- {
- // Use PeekMessage() if the app is active, so we can use idle time to
- // render the scene. Else, use GetMessage() to avoid eating CPU time.
- if( g_bIsActive )
- bGotMsg = PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE );
- else
- bGotMsg = GetMessage( &msg, NULL, 0U, 0U );
-
- if( bGotMsg )
- {
- // Translate and dispatch the message
- TranslateMessage( &msg );
- DispatchMessage( &msg );
- }
- else
- {
- // Render a frame during idle time (no messages are waiting)
- if( g_bDisplayReady )
- {
- FrameMove();
- RenderFrame();
- }
- }
- }
-
- return (int)msg.wParam;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: WndProc()
- // Desc: Callback for all Windows messages
- //-----------------------------------------------------------------------------
- LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
- {
- switch( msg )
- {
- case WM_ACTIVATEAPP:
- g_bIsActive = (BOOL)wParam;
-
- if( g_bIsActive )
- {
- g_bMouseVisible = FALSE;
- DXUtil_Timer( TIMER_START );
- }
- else
- {
- g_bMouseVisible = TRUE;
- DXUtil_Timer( TIMER_STOP );
- }
- break;
-
- case WM_GETMINMAXINFO:
- ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 320;
- ((MINMAXINFO*)lParam)->ptMinTrackSize.y = 200;
- break;
-
- case WM_SETCURSOR:
- if( !g_bMouseVisible && g_dwAppState!=APPSTATE_DISPLAYSPLASH )
- SetCursor( NULL );
- else
- SetCursor( LoadCursor( NULL, IDC_ARROW ) );
- return TRUE;
-
- case WM_SYSCOMMAND:
- // Prevent moving/sizing and power loss
- switch( wParam )
- {
- case SC_MOVE:
- case SC_SIZE:
- case SC_MAXIMIZE:
- case SC_KEYMENU:
- case SC_MONITORPOWER:
- return 1;
- }
- break;
-
- case WM_SYSKEYDOWN:
- // Handle Alt+Enter to do mode-switching
- if( VK_RETURN == wParam )
- {
- SwitchDisplayModes( !g_bFullScreen, g_dwScreenWidth,
- g_dwScreenHeight );
- }
- break;
-
- case WM_KEYDOWN:
- // Move from splash screen when user presses a key
- if( g_dwAppState == APPSTATE_DISPLAYSPLASH )
- {
- if( wParam==VK_ESCAPE )
- {
- // Escape keys exits the app
- PostMessage( hWnd, WM_CLOSE, 0, 0 );
- g_bDisplayReady = FALSE;
- }
- else
- {
- // Get rid of splash bitmap
- DeleteObject( g_hSplashBitmap );
-
- // Advance to the first level
- g_dwAppState = APPSTATE_BEGINLEVELSCREEN;
- DXUtil_Timer( TIMER_START );
- AdvanceLevel();
- }
- }
- return 0;
-
- case WM_PAINT:
- if( g_dwAppState == APPSTATE_DISPLAYSPLASH )
- {
- BITMAP bmp;
- RECT rc;
- GetClientRect( g_hWndMain, &rc );
-
- // Display the splash bitmap in the window
- HDC hDCWindow = GetDC( g_hWndMain );
- HDC hDCImage = CreateCompatibleDC( NULL );
- SelectObject( hDCImage, g_hSplashBitmap );
- GetObject( g_hSplashBitmap, sizeof(bmp), &bmp );
- StretchBlt( hDCWindow, 0, 0, rc.right, rc.bottom,
- hDCImage, 0, 0,
- bmp.bmWidth, bmp.bmHeight, SRCCOPY );
- DeleteDC( hDCImage );
- ReleaseDC( g_hWndMain, hDCWindow );
- }
- else
- {
- if( g_bDisplayReady )
- {
- DrawDisplayList();
- ShowFrame();
- }
- }
- break;
-
- case WM_DESTROY:
- DestroyGameObjects();
- PostQuitMessage( 0 );
- g_bDisplayReady = FALSE;
- break;
- }
-
- return DefWindowProc( hWnd, msg, wParam, lParam );
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: CreateGameObjects()
- // Desc:
- //-----------------------------------------------------------------------------
- HRESULT CreateGameObjects( HWND hWnd )
- {
- HRESULT hr;
-
- // Initialize the DirectInput stuff
- if( FAILED( hr = CreateInputObjects( hWnd ) ) )
- return hr;
-
- // Initialize the DirectSound stuff. Note: if this call fails, we can
- // continue with no sound.
- CreateSoundObjects( hWnd );
-
- // Create the display objects
- if( FAILED( hr = CreateDisplayObjects( hWnd ) ) )
- return hr;
-
- // Add a ship to the displaylist
- g_pShip = new CShip( D3DXVECTOR3(0.0f,0.0f,0.0f) );
- g_pDisplayList = g_pShip;
-
- // Construct the game menus
- ConstructMenus();
-
- // Initial program state is to display the splash screen
- g_dwAppState = APPSTATE_LOADSPLASH;
-
- return S_OK;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: DestroyGameObjects()
- // Desc:
- //-----------------------------------------------------------------------------
- VOID DestroyGameObjects()
- {
- DestroyDisplayObjects();
- DestroySoundObjects();
- DestroyInputObjects();
- DestroyMenus();
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: AdvanceLevel()
- // Desc:
- //-----------------------------------------------------------------------------
- VOID AdvanceLevel()
- {
- // Up the level
- g_dwLevel++;
-
- srand( timeGetTime() );
-
- // Clear any stray objects (anything but the ship) out of the display list
- while( g_pShip->pNext )
- {
- DeleteFromList( g_pShip->pNext );
- }
-
- // Create donuts for the new level
- for( WORD i=0; i<(2*g_dwLevel+3); i++ )
- {
- D3DVECTOR vPosition = 3.0f * D3DXVECTOR3( rnd(), rnd(), 0.0f );
- D3DVECTOR vVelocity = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
-
- AddToList( new CDonut( vPosition, vVelocity ) );
- }
-
- // Delay for 2 seconds before displaying ship
- g_pShip->vPos = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
- g_pShip->vVel = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
- g_pShip->bVisible = FALSE;
- g_pShip->bExploded = FALSE;
- g_pShip->fShowDelay = 2.0f;
-
- // Clear out iput states
- g_fBank = 0.0f;
- g_fThrust = 0.0f;
- g_bFiringWeapons = FALSE;
-
- // Stop engine sounds
- StopSound( g_pEngineIdleSound );
- StopSound( g_pEngineRevSound );
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: DisplayObject()
- // Desc:
- //-----------------------------------------------------------------------------
- DisplayObject::DisplayObject( DWORD type, D3DVECTOR p, D3DVECTOR v )
- {
- // Set object attributes
- pNext = NULL;
- pPrev = NULL;
- bVisible = TRUE;
- dwType = type;
- vPos = p;
- vVel = v;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: C3DSprite()
- // Desc:
- //-----------------------------------------------------------------------------
- C3DSprite::C3DSprite( DWORD type, D3DVECTOR p, D3DVECTOR v )
- :DisplayObject( type, p, v )
- {
- dwColor = 0xffffffff;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: CDonut()
- // Desc:
- //-----------------------------------------------------------------------------
- CDonut::CDonut( D3DVECTOR p, D3DVECTOR v )
- :C3DSprite( OBJ_DONUT, p, v )
- {
- // Set object attributes
- dwTextureWidth = DONUT_WIDTH;
- dwTextureHeight = DONUT_HEIGHT;
- dwTextureOffsetX = 0;
- dwTextureOffsetY = 0;
-
- fSize = dwTextureWidth / 256.0f;
- vVel += 0.5f * D3DXVECTOR3( rnd(), rnd(), 0.0f );
-
- delay = rnd( 3.0f, 12.0f );
- dwFramesPerLine = 8;
- frame = rnd( 0.0f, 30.0f );
- fMaxFrame = NUM_DONUT_FRAMES;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: CPyramid()
- // Desc:
- //-----------------------------------------------------------------------------
- CPyramid::CPyramid( D3DVECTOR p, D3DVECTOR v )
- :C3DSprite( OBJ_PYRAMID, p, v )
- {
- // Set object attributes
- dwTextureWidth = PYRAMID_WIDTH;
- dwTextureHeight = PYRAMID_HEIGHT;
- dwTextureOffsetX = 0;
- dwTextureOffsetY = 0;
-
- fSize = dwTextureWidth / 256.0f;
- vVel += 0.5f * D3DXVECTOR3( rnd(), rnd(), 0.0f );
-
- delay = rnd( 12.0f, 40.0f );
- dwFramesPerLine = 8;
- frame = rnd( 0.0f, 30.0f );
- fMaxFrame = NUM_PYRAMID_FRAMES;
-
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: CSphere()
- // Desc:
- //-----------------------------------------------------------------------------
- CSphere::CSphere( D3DVECTOR p, D3DVECTOR v )
- :C3DSprite( OBJ_SPHERE, p, v )
- {
- // Set object attributes
- dwTextureWidth = SPHERE_WIDTH;
- dwTextureHeight = SPHERE_HEIGHT;
- dwTextureOffsetX = 0;
- dwTextureOffsetY = 128;
-
- fSize = dwTextureWidth / 256.0f;
- vVel += 0.5f * D3DXVECTOR3( rnd(), rnd(), 0.0f );
-
- delay = rnd( 60.0f, 80.0f );
- dwFramesPerLine = 16;
- frame = rnd( 0.0f, 30.0f );
- fMaxFrame = NUM_SPHERE_FRAMES;
- }
-
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: CCube()
- // Desc:
- //-----------------------------------------------------------------------------
- CCube::CCube( D3DVECTOR p, D3DVECTOR v )
- :C3DSprite( OBJ_CUBE, p, v )
- {
- // Set object attributes
- dwTextureWidth = CUBE_WIDTH;
- dwTextureHeight = CUBE_HEIGHT;
- dwTextureOffsetX = 0;
- dwTextureOffsetY = 176;
-
- fSize = dwTextureWidth / 256.0f;
- vVel += 0.5f * D3DXVECTOR3( rnd(), rnd(), 0.0f );
-
- delay = rnd( 32.0f, 80.0f );
- dwFramesPerLine = 16;
- frame = rnd( 0.0f, 30.0f );
- fMaxFrame = NUM_CUBE_FRAMES;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: CCloud()
- // Desc:
- //-----------------------------------------------------------------------------
- CCloud::CCloud( D3DVECTOR p, D3DVECTOR v )
- :C3DSprite( OBJ_CLOUD, p, v )
- {
- // Set object attributes
- dwTextureWidth = CLOUD_WIDTH;
- dwTextureHeight = CLOUD_WIDTH;
- dwTextureOffsetX = 224;
- dwTextureOffsetY = 224;
-
- fSize = dwTextureWidth / 256.0f;
- delay = rnd( 1.0f, 3.0f );
- dwFramesPerLine = 1;
- frame = 0.0f;
- fMaxFrame = 1;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: CBullet()
- // Desc:
- //-----------------------------------------------------------------------------
- CBullet::CBullet( D3DVECTOR p, D3DVECTOR v, DWORD dwCType )
- :C3DSprite( OBJ_BULLET, p, v )
- {
- // Set object attributes
- dwTextureWidth = CLOUD_WIDTH;
- dwTextureHeight = CLOUD_HEIGHT;
- dwTextureOffsetX = 224;
- dwTextureOffsetY = 224;
-
- if( dwCType == 0 )
- dwColor = 0xff2020ff;
- if( dwCType == 1 )
- dwColor = 0xff208020;
- if( dwCType == 2 )
- dwColor = 0xff208080;
- if( dwCType == 3 )
- dwColor = 0xff802020;
-
- fSize = 4 / 256.0f;
- fMaxFrame = NUM_BULLET_FRAMES;
-
- delay = 1000.0f;
- dwFramesPerLine = 1;
- frame = 0.0f;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: CShip()
- // Desc:
- //-----------------------------------------------------------------------------
- CShip::CShip( D3DVECTOR p )
- :DisplayObject( OBJ_SHIP, p, D3DXVECTOR3(0,0,0) )
- {
- fSize = 10.0f / 256.0f;
- bExploded = FALSE;
- fShowDelay = 0.0f;
-
- fRoll = 0.0f;
- fAngle = 0.0f;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: AddToList()
- // Desc:
- //-----------------------------------------------------------------------------
- VOID AddToList( DisplayObject* pObject )
- {
- pObject->pNext = g_pDisplayList->pNext;
- pObject->pPrev = g_pDisplayList;
-
- if( g_pDisplayList->pNext )
- g_pDisplayList->pNext->pPrev = pObject;
- g_pDisplayList->pNext = pObject;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: IsDisplayListEmpty()
- // Desc:
- //-----------------------------------------------------------------------------
- BOOL IsDisplayListEmpty()
- {
- DisplayObject* pObject = g_pDisplayList->pNext;
-
- while( pObject )
- {
- if( pObject->dwType != OBJ_BULLET )
- return FALSE;
-
- pObject = pObject->pNext;
- }
-
- return TRUE;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: LoadTerrainModel()
- // Desc: Loads the 3D geometry for the terrain
- //-----------------------------------------------------------------------------
- HRESULT LoadTerrainModel()
- {
- LPDIRECT3DVERTEXBUFFER8 pVB;
- DWORD dwNumVertices;
- MODELVERTEX* pVertices;
-
- // Delete old object
- SAFE_DELETE( g_pTerrain );
-
- // Create new object
- g_pTerrain = new CD3DMesh();
- if( FAILED( g_pTerrain->Create( g_pd3dDevice, _T("SeaFloor.x") ) ) )
- return E_FAIL;
-
- // Set the FVF to a reasonable type
- g_pTerrain->SetFVF( g_pd3dDevice, D3DFVF_MODELVERTEX );
-
- // Gain access to the model's vertices
- g_pTerrain->GetSysMemMesh()->GetVertexBuffer( &pVB );
- dwNumVertices = g_pTerrain->GetSysMemMesh()->GetNumVertices();
- pVB->Lock( 0, 0, (BYTE**)&pVertices, 0 );
-
- for( DWORD i=0; i<dwNumVertices; i++ )
- {
- pVertices[i].p.x *= 0.1f;
- pVertices[i].p.z *= 0.1f;
- pVertices[i].p.y = HeightField( pVertices[i].p.x, pVertices[i].p.z );
- }
-
- // Done with the vertex buffer
- pVB->Unlock();
- pVB->Release();
-
- return S_OK;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: LoadShipModel()
- // Desc: Loads the 3D geometry for the player's ship
- //-----------------------------------------------------------------------------
- HRESULT LoadShipModel()
- {
- LPDIRECT3DVERTEXBUFFER8 pVB;
- DWORD dwNumVertices;
- MODELVERTEX* pVertices;
- D3DXVECTOR3 vCenter;
- FLOAT fRadius;
-
- // Delete old object
- SAFE_DELETE( g_pShipFileObject );
-
- // Create new object
- g_pShipFileObject = new CD3DMesh();
- if( FAILED( g_pShipFileObject->Create( g_pd3dDevice,
- g_strShipFiles[g_dwCurrentShipType] ) ) )
- return E_FAIL;
-
- // Set the FVF to a reasonable type
- g_pShipFileObject->SetFVF( g_pd3dDevice, D3DFVF_MODELVERTEX );
-
- // Gain access to the model's vertices
- g_pShipFileObject->GetSysMemMesh()->GetVertexBuffer( &pVB );
- dwNumVertices = g_pShipFileObject->GetSysMemMesh()->GetNumVertices();
- pVB->Lock( 0, 0, (BYTE**)&pVertices, 0 );
-
- // Scale the new object to a standard size
- D3DXComputeBoundingSphere( pVertices, dwNumVertices,
- D3DFVF_MODELVERTEX, &vCenter, &fRadius );
- for( DWORD i=0; i<dwNumVertices; i++ )
- {
- pVertices[i].p /= 12*fRadius;
- }
-
- // Done with the vertex buffer
- pVB->Unlock();
- pVB->Release();
-
- return S_OK;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: SwitchModel()
- // Desc:
- //-----------------------------------------------------------------------------
- HRESULT SwitchModel()
- {
- // Select next model
- g_dwCurrentShipType++;
- if( g_dwCurrentShipType >= g_dwNumShipTypes )
- g_dwCurrentShipType = 0L;
-
- // Create new object
- if( SUCCEEDED( LoadShipModel() ) )
- {
- // Initialize the new object's device dependent objects
- if( SUCCEEDED( g_pShipFileObject->RestoreDeviceObjects( g_pd3dDevice ) ) )
- return S_OK;
- }
-
- // Return with a fatal error
- PostMessage( g_hWndMain, WM_CLOSE, 0, 0 );
- return E_FAIL;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: FrameMove()
- // Desc:
- //-----------------------------------------------------------------------------
- HRESULT FrameMove()
- {
- switch( g_dwAppState )
- {
- case APPSTATE_LOADSPLASH:
- // Set the app state to displaying splash
- g_dwAppState = APPSTATE_DISPLAYSPLASH;
-
- // Draw the splash bitmap
- g_hSplashBitmap = (HBITMAP)LoadImage( GetModuleHandle( NULL ),
- TEXT("SPLASH"), IMAGE_BITMAP,
- 0, 0, LR_CREATEDIBSECTION );
- SendMessage( g_hWndMain, WM_PAINT, 0, 0 );
- break;
-
- case APPSTATE_ACTIVE:
- UpdateDisplayList();
- CheckForHits();
-
- if( IsDisplayListEmpty() )
- {
- AdvanceLevel();
- g_dwAppState = APPSTATE_BEGINLEVELSCREEN;
- }
- break;
-
- case APPSTATE_BEGINLEVELSCREEN:
- PlaySound( g_pBeginLevelSound );
- DXUtil_Timer( TIMER_RESET );
- g_dwAppState = APPSTATE_DISPLAYLEVELSCREEN;
- break;
-
- case APPSTATE_DISPLAYLEVELSCREEN:
- // Only show the Level intro screen for 3 seconds
-
- if( DXUtil_Timer( TIMER_GETAPPTIME ) > 3.0f )
- {
- g_dwAppState = APPSTATE_ACTIVE;
- }
- break;
- }
-
- return S_OK;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: RenderFrame()
- // Desc:
- //-----------------------------------------------------------------------------
- HRESULT RenderFrame()
- {
- // Test cooperative level
- HRESULT hr;
-
- // Test the cooperative level to see if it's okay to render
- if( FAILED( hr = g_pd3dDevice->TestCooperativeLevel() ) )
- {
- // If the device was lost, do not render until we get it back
- if( D3DERR_DEVICELOST == hr )
- return S_OK;
-
- // Check if the device needs to be resized.
- if( D3DERR_DEVICENOTRESET == hr )
- {
- g_bDisplayReady = FALSE;
-
- InvalidateDisplayObjects();
-
- // Resize the device
- if( SUCCEEDED( g_pd3dDevice->Reset( &g_d3dpp ) ) )
- {
- // Initialize the app's device-dependent objects
- if( SUCCEEDED( RestoreDisplayObjects() ) )
- {
- g_bDisplayReady = TRUE;
- return S_OK;
- }
- }
-
- PostMessage( g_hWndMain, WM_CLOSE, 0, 0 );
- }
- return hr;
- }
-
- // Render the scene based on current state of the app
- switch( g_dwAppState )
- {
- case APPSTATE_LOADSPLASH:
- // Nothing to render while loading the splash screen
- break;
-
- case APPSTATE_DISPLAYSPLASH:
- // Rendering of the splash screen is handled by WM_PAINT
- break;
-
- case APPSTATE_BEGINLEVELSCREEN:
- // Nothing to render while starting sound to advance a level
- break;
-
- case APPSTATE_DISPLAYLEVELSCREEN:
- DisplayLevelIntroScreen( g_dwLevel );
- ShowFrame();
- break;
-
- case APPSTATE_ACTIVE:
- DrawDisplayList();
- ShowFrame();
- break;
- }
-
- return S_OK;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: DarkenScene()
- // Desc:
- //-----------------------------------------------------------------------------
- VOID DarkenScene( FLOAT fAmount )
- {
- if( g_pd3dDevice==NULL )
- return;
-
- // Setup a dark square to cover the scene
- DWORD dwAlpha = (fAmount<1.0f) ? ((DWORD)(255*fAmount))<<24L : 0xff000000;
- SCREENVERTEX* v;
- g_pViewportVB->Lock( 0, 0, (BYTE**)&v, 0 );
- v[0].color = v[1].color = v[2].color = v[3].color = dwAlpha;
- g_pViewportVB->Unlock();
-
- // Set renderstates
- g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
- g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
- g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
- g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE );
- g_pd3dDevice->SetTexture( 0, NULL );
-
- // Draw a big, gray square
- g_pd3dDevice->SetVertexShader( D3DFVF_SCREENVERTEX );
- g_pd3dDevice->SetStreamSource( 0, g_pViewportVB, sizeof(SCREENVERTEX) );
- g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP,0, 2 );
-
- // Restore states
- g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
- g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
- g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
- g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
- g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
- g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- VOID RenderFieryText( CD3DFont* pFont, TCHAR* strText )
- {
- if( NULL==pFont || NULL==strText )
- return;
-
- // Render the fiery portion of the text
- for( DWORD i=0; i<20; i++ )
- {
- FLOAT x = -0.5f;
- FLOAT y = 1.8f;
-
- FLOAT v1 = rnd(0.0f, 1.0f);
- FLOAT red1 = v1*v1*v1;
- FLOAT grn1 = v1*v1;
- FLOAT blu1 = v1;
-
-
- FLOAT a1 = rnd(0.0f, 2*D3DX_PI);
- FLOAT r1 = v1 * 0.05f;
-
- x += r1*sinf(a1);
- y += r1*cosf(a1);
-
- if( cosf(a1) < 0.0f )
- y -= 2*r1*cosf(a1)*cosf(a1);
-
- DWORD r = (CHAR)((1.0f-red1)*256.0f);
- DWORD g = (CHAR)((1.0f-grn1)*256.0f);
- DWORD b = (CHAR)((1.0f-blu1)*256.0f);
- DWORD a = (CHAR)255;
- DWORD dwColor = (a<<24) + (r<<16) + (g<<8) + b;
-
- g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
- g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
-
- pFont->DrawTextScaled( x, y, 0.9f, 0.25f, 0.25f, dwColor, strText, D3DFONT_FILTERED );
- }
-
- // Render the plain, black portion of the text
- g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
- g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
- FLOAT x = -0.5f;
- FLOAT y = 1.8f;
- pFont->DrawTextScaled( x, y, 0.9f, 0.25f, 0.25f, 0xff000000, strText, D3DFONT_FILTERED );
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: DisplayLevelIntroScreen()
- // Desc:
- //-----------------------------------------------------------------------------
- VOID DisplayLevelIntroScreen( DWORD dwLevel )
- {
- if( g_pd3dDevice==NULL )
- return;
-
- // Begin the scene
- if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
- {
- // Erase the screen
- g_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0L, 1.0f, 0L );
-
- TCHAR strLevel[80];
- _stprintf( strLevel, _T("Level %ld"), dwLevel );
- RenderFieryText( g_pGameFont, strLevel );
-
- DarkenScene( 1.0f - sinf(D3DX_PI*DXUtil_Timer( TIMER_GETAPPTIME )/3.0f) );
-
- // End the scene
- g_pd3dDevice->EndScene();
- }
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: UpdateDisplayList()
- // Desc:
- //-----------------------------------------------------------------------------
- VOID UpdateDisplayList()
- {
- DisplayObject* pObject;
-
- // Get the time lapsed since the last frame
- static FLOAT fLastTime = 0.0f;
- FLOAT fTimeLapsed = DXUtil_Timer( TIMER_GETAPPTIME ) - fLastTime;
- if( fTimeLapsed <= 0.0f )
- fTimeLapsed = 0.01f;
- fLastTime = DXUtil_Timer( TIMER_GETAPPTIME );
-
- // Read input from the joystick/keyboard/etc
- GetInput();
-
- // Check for game menu condition
- if( g_pCurrentMenu )
- {
- UpdateMenus();
- return;
- }
-
- if( g_bPaused )
- return;
-
- if( g_pShip->fShowDelay > 0.0f )
- {
- g_pShip->fShowDelay -= fTimeLapsed;
-
- if( g_pShip->fShowDelay <= 0.0f )
- {
- g_pShip->vVel = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
- g_pShip->fShowDelay = 0.0f;
- g_pShip->bVisible = TRUE;
- g_pShip->bExploded = FALSE;
- }
- }
-
- // Update the ship
- if( g_pShip->bVisible )
- {
- g_pShip->vPos += g_pShip->vVel * fTimeLapsed;
- }
-
- // Apply banking motion
- g_pShip->fRoll += g_fBank * 1.0f * fTimeLapsed;
- if( g_pShip->fRoll > 0.5f )
- g_pShip->fRoll = 0.5f;
- if( g_pShip->fRoll < -0.5f )
- g_pShip->fRoll = -0.5f;
-
- g_pShip->fAngle += 5 * g_pShip->fRoll * fTimeLapsed;
-
- if( g_fBank < 0.2f && g_fBank > -0.2f )
- {
- g_pShip->fRoll *= 0.95f;
- }
-
- // Slow the ship down
- g_pShip->vVel.x *= 0.97f;
- g_pShip->vVel.y *= 0.97f;
-
- // Apply thrust
- g_pShip->vVel.x += sinf( g_pShip->fAngle ) * g_fThrust * 5.0f * fTimeLapsed;
- g_pShip->vVel.y += -cosf( g_pShip->fAngle ) * g_fThrust * 5.0f * fTimeLapsed;
-
- // Play thrusting sounds
- {
- static bPlayingEngineRevSound = FALSE;
-
- if( g_fThrust > 0.5f )
- {
- if( FALSE == bPlayingEngineRevSound )
- {
- bPlayingEngineRevSound = TRUE;
- }
- }
- else
- {
- if( TRUE == bPlayingEngineRevSound )
- {
- StopSound( g_pEngineRevSound );
- bPlayingEngineRevSound = FALSE;
- }
- }
- }
-
- g_fBulletRechargeTime -= fTimeLapsed;
-
- // Fire a bullet
- if( g_bFiringWeapons && g_fBulletRechargeTime <= 0.0f )
- {
- // Ship must be visible and have no shields on to fire
- if( g_pShip->bVisible )
- {
- // Bullets cost one score point
- if( g_dwScore )
- g_dwScore--;
-
- // Play the "fire" effects
- PlaySound( g_pFireBulletSound );
-
- // Add a bullet to the display list
- if( g_dwBulletType == 0 )
- {
- D3DXVECTOR3 vDir = D3DXVECTOR3( sinf( g_pShip->fAngle ), -cosf( g_pShip->fAngle ), 0.0f );
-
- AddToList( new CBullet( g_pShip->vPos, g_pShip->vVel + 2*vDir, 0 ) );
- g_fBulletRechargeTime = 0.05f;
- }
- else if( g_dwBulletType == 1 )
- {
- D3DXVECTOR3 vOffset = 0.02f * D3DXVECTOR3( cosf(g_pShip->fAngle), sinf(g_pShip->fAngle), 0.0f );
- D3DXVECTOR3 vDir = D3DXVECTOR3( sinf( g_pShip->fAngle ), -cosf( g_pShip->fAngle ), 0.0f );
-
- AddToList( new CBullet( g_pShip->vPos + vOffset, g_pShip->vVel + 2*vDir, 1 ) );
- AddToList( new CBullet( g_pShip->vPos - vOffset, g_pShip->vVel + 2*vDir, 1 ) );
- g_fBulletRechargeTime = 0.10f;
- }
- else if( g_dwBulletType == 2 )
- {
- FLOAT fBulletAngle = g_pShip->fAngle + 0.2f*rnd();
- D3DXVECTOR3 vDir = D3DXVECTOR3( sinf(fBulletAngle), -cosf(fBulletAngle), 0.0f );
-
- AddToList( new CBullet( g_pShip->vPos, g_pShip->vVel + 2*vDir, 2 ) );
- g_fBulletRechargeTime = 0.01f;
- }
- else
- {
- for( DWORD i=0; i<50; i++ )
- {
- FLOAT fBulletAngle = g_pShip->fAngle + D3DX_PI*rnd();
- D3DXVECTOR3 vDir = D3DXVECTOR3( sinf(fBulletAngle), -cosf(fBulletAngle), 0.0f );
-
- AddToList( new CBullet( g_pShip->vPos, 2*vDir, 3 ) );
- }
-
- g_fBulletRechargeTime = 1.0f;
- }
- }
- }
-
- // Keep ship in bounds
- if( g_pShip->vPos.x < -5.0f || g_pShip->vPos.x > +5.0f ||
- g_pShip->vPos.y < -5.0f || g_pShip->vPos.y > +5.0f )
- {
- D3DXVec3Normalize( &g_pShip->vVel, &g_pShip->vPos );
- g_pShip->vVel.x *= -1.0f;
- g_pShip->vVel.y *= -1.0f;
- g_pShip->vVel.z *= -1.0f;
- }
-
- // Finally, move all objects on the screen
- for( pObject = g_pDisplayList; pObject; pObject = pObject->pNext )
- {
- // The ship is moved by the code above
- if( pObject->dwType == OBJ_SHIP )
- continue;
-
- C3DSprite* pSprite = (C3DSprite*)pObject;
-
- // Update the position and animation frame
- pSprite->vPos += pSprite->vVel * fTimeLapsed;
- pSprite->frame += pSprite->delay * fTimeLapsed;
-
- // If this is an "expired" cloud, removed it from list
- if( pObject->dwType == OBJ_CLOUD )
- {
- if( pSprite->frame >= pSprite->fMaxFrame )
- {
- DisplayObject* pVictim = pObject;
- pObject = pObject->pPrev;
- DeleteFromList( pVictim );
- }
- }
- else if( pObject->dwType == OBJ_BULLET )
- {
- // Remove bullets when they leave the scene
- if( pObject->vPos.x < -6.0f || pObject->vPos.x > +6.0f ||
- pObject->vPos.y < -6.0f || pObject->vPos.y > +6.0f )
- {
- DisplayObject* pVictim = pObject;
- pObject = pObject->pPrev;
- DeleteFromList( pVictim );
- }
- }
- else if( pObject->dwType != OBJ_CLOUD )
- {
- // Keep object in bounds in X
- if( pObject->vPos.x < -4.0f || pObject->vPos.x > +4.0f )
- {
- if( pObject->vPos.x < -4.0f ) pObject->vPos.x = -4.0f;
- if( pObject->vPos.x > +4.0f ) pObject->vPos.x = +4.0f;
- pObject->vVel.x = -pObject->vVel.x;
- }
-
- // Keep object in bounds in Y
- if( pObject->vPos.y < -4.0f || pObject->vPos.y > +4.0f )
- {
- if( pObject->vPos.y < -4.0f ) pObject->vPos.y = -4.0f;
- if( pObject->vPos.y > +4.0f ) pObject->vPos.y = +4.0f;
- pObject->vVel.y = -pObject->vVel.y;
- }
-
- // Keep animation frame in bounds
- if( pSprite->frame < 0.0f )
- pSprite->frame += pSprite->fMaxFrame;
- if( pSprite->frame >= pSprite->fMaxFrame )
- pSprite->frame -= pSprite->fMaxFrame;
- }
- }
-
- D3DXVECTOR3 vEyePt[NUMVIEWMODES];
- D3DXVECTOR3 vLookatPt[NUMVIEWMODES];
- D3DXVECTOR3 vUpVec[NUMVIEWMODES];
-
- // Update the view
- if( g_bChangeView )
- {
- g_bAnimatingViewChange = TRUE;
- g_bChangeView = FALSE;
- }
-
- if( g_bAnimatingViewChange )
- {
- g_fViewTransition += fTimeLapsed;
-
- if( g_fViewTransition >= 1.0f )
- {
- g_dwViewMode++;
- if( g_dwViewMode >= NUMVIEWMODES )
- g_dwViewMode = 0;
-
- g_fViewTransition = 0.0f;
- g_bAnimatingViewChange = FALSE;
- }
- }
-
- FLOAT fX = g_pShip->vPos.x;
- FLOAT fZ = -g_pShip->vPos.y;
- FLOAT fY = 0.1f + HeightField( fX, fZ );
-
- // View mode 0 (third person)
- vEyePt[0] = D3DXVECTOR3( fX-sinf(g_pShip->fAngle)/2, fY+0.2f, fZ-cosf(g_pShip->fAngle)/2 );
- vLookatPt[0] = D3DXVECTOR3( fX+sinf(g_pShip->fAngle)/2, fY, fZ+cosf(g_pShip->fAngle)/2 );
- vUpVec[0] = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
-
- // View mode 1 (first person)
- FLOAT fX2 = fX+sinf(g_pShip->fAngle);
- FLOAT fZ2 = fZ+cosf(g_pShip->fAngle);
- FLOAT fY2 = 0.1f + HeightField( fX2, fZ2 );
- vEyePt[1] = D3DXVECTOR3( fX, fY+0.1f, fZ );
- vLookatPt[1] = D3DXVECTOR3( fX2, fY2+0.1f, fZ2 );
- vUpVec[1] = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
-
- // View mode 2 (top down view)
- vEyePt[2] = D3DXVECTOR3( fX+1.5f, fY+1.5f, fZ+1.5f );
- vLookatPt[2] = D3DXVECTOR3( fX, fY, fZ );
- vUpVec[2] = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
-
- DWORD start = g_dwViewMode;
- DWORD end = ( start < (NUMVIEWMODES-1) ) ? g_dwViewMode+1: 0;
-
- if( start == 1 && g_fViewTransition<0.2f)
- g_bFirstPersonView = TRUE;
- else
- g_bFirstPersonView = FALSE;
-
- D3DXVECTOR3 vEyePt0 = (1.0f-g_fViewTransition)*vEyePt[start] + g_fViewTransition*vEyePt[end];
- D3DXVECTOR3 vLookatPt0 = (1.0f-g_fViewTransition)*vLookatPt[start] + g_fViewTransition*vLookatPt[end];
- D3DXVECTOR3 vUpVec0 = (1.0f-g_fViewTransition)*vUpVec[start] + g_fViewTransition*vUpVec[end];
-
- // Shake screen if ship exploded
- if( g_pShip->bExploded == TRUE )
- vEyePt0 += D3DXVECTOR3( rnd(), rnd(), rnd() ) * g_pShip->fShowDelay / 50.0f;
-
- g_Camera.SetViewParams( vEyePt0, vLookatPt0, vUpVec0 );
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: CheckForHits()
- // Desc:
- //-----------------------------------------------------------------------------
- VOID CheckForHits()
- {
- DisplayObject* pObject;
- DisplayObject* pBullet;
-
- for( pBullet = g_pDisplayList; pBullet; pBullet = pBullet->pNext )
- {
- BOOL bBulletHit = FALSE;
-
- // Only bullet objects and the ship (if shieleds are on) can hit
- // other objects. Skip all others.
- if( (pBullet->dwType != OBJ_BULLET) && (pBullet->dwType != OBJ_SHIP) )
- continue;
-
- for( pObject = g_pDisplayList->pNext; pObject; pObject = pObject->pNext )
- {
- // Only trying to hit explodable targets
- if( ( pObject->dwType != OBJ_DONUT ) &&
- ( pObject->dwType != OBJ_PYRAMID ) &&
- ( pObject->dwType != OBJ_SPHERE ) &&
- ( pObject->dwType != OBJ_CUBE ) )
- continue;
-
- // Check if bullet is in radius of object
- FLOAT fDistance = D3DXVec3Length( &(pBullet->vPos - pObject->vPos) );
-
- if( fDistance < (pObject->fSize+pBullet->fSize) )
- {
- // The object was hit
- switch( pObject->dwType )
- {
- case OBJ_DONUT:
- PlaySound( g_pDonutExplodeSound );
- AddToList( new CPyramid( pObject->vPos, pObject->vVel ) );
- AddToList( new CPyramid( pObject->vPos, pObject->vVel ) );
- AddToList( new CPyramid( pObject->vPos, pObject->vVel ) );
- AddToList( new CPyramid( pObject->vPos, pObject->vVel ) );
- g_dwScore += 10;
- break;
-
- case OBJ_PYRAMID:
- PlaySound( g_pPyramidExplodeSound );
- AddToList( new CCube( pObject->vPos, pObject->vVel ) );
- AddToList( new CCube( pObject->vPos, pObject->vVel ) );
- AddToList( new CCube( pObject->vPos, pObject->vVel ) );
- AddToList( new CCube( pObject->vPos, pObject->vVel ) );
- g_dwScore += 20;
- break;
-
- case OBJ_CUBE:
- PlaySound( g_pCubeExplodeSound );
- AddToList( new CSphere( pObject->vPos, pObject->vVel ) );
- g_dwScore += 40;
- break;
-
- case OBJ_SPHERE:
- PlaySound( g_pSphereExplodeSound );
- g_dwScore += 20;
- break;
- }
-
- // Add explosion effects to scene
- for( DWORD c=0; c<4; c++ )
- AddToList( new CCloud( pObject->vPos, 0.05f*D3DXVECTOR3(rnd(),rnd(),0.0f) ) );
-
- // Remove the victim from the scene
- DisplayObject* pVictim = pObject;
- pObject = pObject->pPrev;
- DeleteFromList( pVictim );
-
- bBulletHit = TRUE;
- }
-
- if( bBulletHit )
- {
- if( pBullet->dwType == OBJ_SHIP )
- {
- bBulletHit = FALSE;
-
- if( g_pShip->bVisible )
- {
- // Ship has exploded
- PlaySound( g_pShipExplodeSound );
-
- if( g_dwScore < 150 )
- g_dwScore = 0;
- else
- g_dwScore -= 150;
-
- // Add explosion debris to scene
- for( DWORD sphere=0; sphere<4; sphere++ )
- AddToList( new CSphere( g_pShip->vPos, pObject->vVel ) );
-
- for( DWORD bullet=0; bullet<20; bullet++ )
- {
- FLOAT angle = D3DX_PI * rnd();
- D3DVECTOR vDir = D3DXVECTOR3(cosf(angle),sinf(angle),0.0f);
- AddToList( new CBullet( g_pShip->vPos, 500.0f*vDir, 0 ) );
- }
-
- for( DWORD cloud=0; cloud<100; cloud++ )
- {
- FLOAT magnitude = 1.0f + 0.1f*rnd();
- FLOAT angle = D3DX_PI * rnd();
- D3DVECTOR vDir = D3DXVECTOR3(cosf(angle),sinf(angle),0.0f);
-
- AddToList( new CCloud( g_pShip->vPos, magnitude*vDir ) );
- }
-
- // Clear out ship params
- g_pShip->vVel.x = 0.0f;
- g_pShip->vVel.y = 0.0f;
- g_fThrust = 0.0f;
- g_fBank = 0.0f;
-
- // Delay for 2 seconds before displaying ship
- g_pShip->fShowDelay = 2.0f;
- g_pShip->bVisible = FALSE;
- g_pShip->bExploded = TRUE;
- }
- }
-
- break;
- }
- }
-
- if( bBulletHit )
- {
- DisplayObject* pLastBullet = pBullet;
- pBullet = pBullet->pPrev;
- DeleteFromList( pLastBullet );
- }
- }
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: DrawDisplayList()
- // Desc:
- //-----------------------------------------------------------------------------
- VOID DrawDisplayList()
- {
- TCHAR strBuffer[80];
-
- // Set the world matrix
- D3DXMATRIX matWorld;
- D3DXMatrixIdentity( &matWorld );
- g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
-
- // Set the app view matrix for normal viewing
- g_pd3dDevice->SetTransform( D3DTS_VIEW, &g_Camera.GetViewMatrix() );
-
- g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
- g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
- g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
- g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
- g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
- g_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
- g_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
- g_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
- g_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
- g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
- g_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE, FALSE );
- g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
- g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
- g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x33333333 );
-
- // Begin the scene
- if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
- {
- // Clear the display
- g_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0L, 1.0f, 0L );
-
- // Draw the terrain
- g_pTerrain->Render( g_pd3dDevice );
-
- // Render the ship
- if( g_pShip->bVisible && g_bFirstPersonView == FALSE )
- {
- // Point of ship, on terrain
- D3DXVECTOR3 vShipPt;
- vShipPt.x = g_pShip->vPos.x;
- vShipPt.z = -g_pShip->vPos.y;
- vShipPt.y = 0.1f + HeightField( vShipPt.x, vShipPt.z );
-
- // Point ahead of ship, on terrain
- D3DXVECTOR3 vForwardPt;
- vForwardPt.x = vShipPt.x+sinf(g_pShip->fAngle);
- vForwardPt.z = vShipPt.z+cosf(g_pShip->fAngle);
- vForwardPt.y = 0.1f + HeightField( vForwardPt.x, vForwardPt.z );
-
- // Point to side of ship, on terrain
- D3DXVECTOR3 vSidePt;
- vSidePt.x = vShipPt.x+sinf(g_pShip->fAngle + D3DX_PI/2.0f);
- vSidePt.z = vShipPt.z+cosf(g_pShip->fAngle + D3DX_PI/2.0f);
- vSidePt.y = 0.1f + HeightField( vSidePt.x, vSidePt.z );
-
- // Compute vectors of the ship's orientation
- D3DXVECTOR3 vForwardDir = vForwardPt - vShipPt;
- D3DXVECTOR3 vSideDir = vSidePt - vShipPt;
- D3DXVECTOR3 vNormalDir;
- D3DXVec3Cross( &vNormalDir, &vForwardDir, &vSideDir );
-
- // Construct matrix to orient ship
- D3DXMATRIX matWorld, matLookAt, matRotateZ;
- D3DXMatrixRotationZ( &matRotateZ, g_pShip->fRoll );
- D3DXMatrixLookAtLH( &matLookAt, &vShipPt, &(vShipPt-vForwardDir), &vNormalDir );
- D3DXMatrixInverse( &matLookAt, NULL, &matLookAt );
- D3DXMatrixIdentity( &matWorld );
- D3DXMatrixMultiply( &matWorld, &matWorld, &matRotateZ );
- D3DXMatrixMultiply( &matWorld, &matWorld, &matLookAt );
-
- // Set renderstates for rendering the ship
- g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
- g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
- g_pd3dDevice->SetRenderState( D3DRS_NORMALIZENORMALS, TRUE );
- g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
- g_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE );
-
- // Render the ship - opaque parts
- g_pShipFileObject->Render( g_pd3dDevice, TRUE, FALSE );
-
- // Render the ship - transparent parts
- g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
- g_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );
- g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
- g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
- g_pShipFileObject->Render( g_pd3dDevice, FALSE, TRUE );
- g_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, TRUE );
- }
-
- // Remaining objects don't need lighting
- g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
-
- // Enable alpha blending and testing
- g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
- g_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE );
- g_pd3dDevice->SetRenderState( D3DRS_ALPHAREF, 0x08 );
- g_pd3dDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL );
-
- // Display all visible objects in the display list
- for( DisplayObject* pObject = g_pDisplayList; pObject; pObject = pObject->pNext )
- {
- if( !pObject->bVisible )
- continue;
- if( pObject->dwType == OBJ_SHIP )
- continue;
- if( pObject->dwType == OBJ_BULLET )
- continue;
-
- // This is really a 3D sprite
- C3DSprite* pSprite = (C3DSprite*)pObject;
-
- FLOAT fX = pObject->vPos.x;
- FLOAT fZ = -pObject->vPos.y;
- FLOAT fY = HeightField( fX, fZ );
-
- FLOAT x1 = -pObject->fSize;
- FLOAT x2 = pObject->fSize;
- FLOAT y1 = -pObject->fSize;
- FLOAT y2 = pObject->fSize;
-
- FLOAT u1 = (FLOAT)(pSprite->dwTextureOffsetX + pSprite->dwTextureWidth *(((int)pSprite->frame)%pSprite->dwFramesPerLine));
- FLOAT v1 = (FLOAT)(pSprite->dwTextureOffsetY + pSprite->dwTextureHeight*(((int)pSprite->frame)/pSprite->dwFramesPerLine));
-
- FLOAT tu1 = u1 / (256.0f-1.0f);
- FLOAT tv1 = v1 / (256.0f-1.0f);
- FLOAT tu2 = (u1 + pSprite->dwTextureWidth -1) / (256.0f-1.0f);
- FLOAT tv2 = (v1 + pSprite->dwTextureHeight-1) / (256.0f-1.0f);
-
- // Set the game texture
- switch( pObject->dwType )
- {
- case OBJ_DONUT:
- case OBJ_CUBE:
- case OBJ_SPHERE:
- g_pd3dDevice->SetTexture( 0, g_pGameTexture1 );
- break;
- case OBJ_PYRAMID:
- case OBJ_CLOUD:
- g_pd3dDevice->SetTexture( 0, g_pGameTexture2 );
- break;
- }
-
- // Translate the billboard into place
- D3DXMATRIX mat = g_Camera.GetBillboardMatrix();
- mat._41 = fX;
- mat._42 = fY;
- mat._43 = fZ;
- g_pd3dDevice->SetTransform( D3DTS_WORLD, &mat );
-
- DWORD dwColor = pSprite->dwColor;
-
- g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
- g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
- g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
- g_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, TRUE );
-
- if( pObject->dwType == OBJ_CLOUD )
- {
- DWORD red = 255-(int)(pSprite->frame*255.0f);
- DWORD grn = 255-(int)(pSprite->frame*511.0f);
- DWORD blu = 255-(int)(pSprite->frame*1023.0f);
- if( grn > 255 ) grn = 0;
- if( blu > 255 ) blu = 0;
- dwColor = 0xff000000 + (red<<16) + (grn<<8) + blu;
-
- g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
- g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
- g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
- g_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );
- }
-
- FLOAT h = 300.0f*pObject->vPos.z + 0.1f;
-
- SPRITEVERTEX* v;
- g_pSpriteVB->Lock( 0, 0, (BYTE**)&v, 0 );
- v[0].p = D3DXVECTOR3(x1,y1+h,0); v[0].color=dwColor; v[0].tu=tu1; v[0].tv=tv2;
- v[1].p = D3DXVECTOR3(x1,y2+h,0); v[1].color=dwColor; v[1].tu=tu1; v[1].tv=tv1;
- v[2].p = D3DXVECTOR3(x2,y1+h,0); v[2].color=dwColor; v[2].tu=tu2; v[2].tv=tv2;
- v[3].p = D3DXVECTOR3(x2,y2+h,0); v[3].color=dwColor; v[3].tu=tu2; v[3].tv=tv1;
- g_pSpriteVB->Unlock();
-
- // Render the billboarded sprite
- g_pd3dDevice->SetVertexShader( D3DFVF_SPRITEVERTEX );
- g_pd3dDevice->SetStreamSource( 0, g_pSpriteVB, sizeof(SPRITEVERTEX) );
- g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
- }
-
- // Display all bullets
- for( pObject = g_pDisplayList; pObject; pObject = pObject->pNext )
- {
- if( pObject->dwType != OBJ_BULLET )
- continue;
-
- // This is really a 3D sprite
- C3DSprite* pSprite = (C3DSprite*)pObject;
-
- FLOAT u1 = (FLOAT)(pSprite->dwTextureOffsetX + pSprite->dwTextureWidth *(((int)pSprite->frame)%pSprite->dwFramesPerLine));
- FLOAT v1 = (FLOAT)(pSprite->dwTextureOffsetY + pSprite->dwTextureHeight*(((int)pSprite->frame)/pSprite->dwFramesPerLine));
- u1 = (FLOAT)(pSprite->dwTextureOffsetX);
- v1 = (FLOAT)(pSprite->dwTextureOffsetY);
-
- FLOAT tu1 = u1 / (256.0f-1.0f);
- FLOAT tv1 = v1 / (256.0f-1.0f);
- FLOAT tu2 = (u1 + pSprite->dwTextureWidth -1) / (256.0f-1.0f);
- FLOAT tv2 = (v1 + pSprite->dwTextureHeight-1) / (256.0f-1.0f);
-
- // Set render states
- g_pd3dDevice->SetTexture( 0, g_pGameTexture2 );
- g_pd3dDevice->SetVertexShader( D3DFVF_SPRITEVERTEX );
- g_pd3dDevice->SetStreamSource( 0, g_pSpriteVB, sizeof(SPRITEVERTEX) );
- g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
- g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
- g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
- g_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );
-
- FLOAT x1 = -0.01f;
- FLOAT x2 = 0.01f;
- FLOAT y1 = -0.01f;
- FLOAT y2 = 0.01f;
-
- DWORD dwColor = pSprite->dwColor;
-
- for( DWORD a=0; a<6; a++ )
- {
- FLOAT fX = pObject->vPos.x - a*a*0.0005f*pObject->vVel.x;
- FLOAT fZ = -pObject->vPos.y + a*a*0.0005f*pObject->vVel.y;
- FLOAT fY = HeightField( fX, fZ );
-
- // Translate the billboard into place
- D3DXMATRIX mat = g_Camera.GetBillboardMatrix();
- mat._41 = fX;
- mat._42 = fY;
- mat._43 = fZ;
- g_pd3dDevice->SetTransform( D3DTS_WORLD, &mat );
-
- FLOAT h = 300.0f*pObject->vPos.z + 0.1f;
-
- SPRITEVERTEX* v;
- g_pSpriteVB->Lock( 0, 0, (BYTE**)&v, 0 );
- v[0].p = D3DXVECTOR3(x1,y1+h,0); v[0].color=dwColor; v[0].tu=tu1; v[0].tv=tv2;
- v[1].p = D3DXVECTOR3(x1,y2+h,0); v[1].color=dwColor; v[1].tu=tu1; v[1].tv=tv1;
- v[2].p = D3DXVECTOR3(x2,y1+h,0); v[2].color=dwColor; v[2].tu=tu2; v[2].tv=tv2;
- v[3].p = D3DXVECTOR3(x2,y2+h,0); v[3].color=dwColor; v[3].tu=tu2; v[3].tv=tv1;
- g_pSpriteVB->Unlock();
-
- // Render the billboarded sprite
- g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
- }
- }
-
- // Restore state
- g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
- g_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, TRUE );
-
- // Display score
- _stprintf( strBuffer, _T("Score: %08ld"), g_dwScore );
- g_pGameFont->DrawTextScaled( -1.0f, 1.0f, 0.9f, 0.05f, 0.05f,
- 0xffffff00, strBuffer, D3DFONT_FILTERED );
-
- // Display ship type
- _stprintf( strBuffer, _T("Ship: %s"), g_strShipNames[g_dwCurrentShipType] );
- g_pGameFont->DrawTextScaled( 0.0f, 1.0f, 0.9f, 0.05f, 0.05f,
- 0xffffff00, strBuffer, D3DFONT_FILTERED );
-
- // Display weapon type
- TCHAR* strWeapon;
- if( g_dwBulletType == 0 ) strWeapon = _T("Weapon: Blaster");
- else if( g_dwBulletType == 1 ) strWeapon = _T("Weapon: Double blaster");
- else if( g_dwBulletType == 2 ) strWeapon = _T("Weapon: Spray gun");
- else strWeapon = _T("Weapon: Proximity killer");
- g_pGameFont->DrawTextScaled( 0.0f, 1.1f, 0.9f, 0.05f, 0.05f,
- 0xffffff00, strWeapon, D3DFONT_FILTERED );
-
- // Render "Paused" text if game is paused
- if( g_bPaused && g_pGameFont )
- {
- DarkenScene( 0.5f );
- RenderFieryText( g_pMenuFont, _T("Paused") );
- }
-
- if( g_pShip->fShowDelay > 0.0f )
- DarkenScene( g_pShip->fShowDelay/2.0f );
-
- // Render game menu
- if( g_pCurrentMenu )
- {
- DarkenScene( 0.5f );
- g_pCurrentMenu->Render( g_pd3dDevice, g_pMenuFont );
- }
-
- g_pd3dDevice->EndScene();
- }
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: DeleteFromList()
- // Desc:
- //-----------------------------------------------------------------------------
- VOID DeleteFromList( DisplayObject* pObject )
- {
- if( pObject->pNext )
- pObject->pNext->pPrev = pObject->pPrev;
- if( pObject->pPrev )
- pObject->pPrev->pNext = pObject->pNext;
- delete( pObject );
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- VOID ConstructMenus()
- {
- // Build video sub menu
- CMenuItem* pVideoSubMenu = new CMenuItem( _T("Video Menu"), MENU_VIDEO );
- pVideoSubMenu->Add( new CMenuItem( _T("Windowed"), MENU_WINDOWED ) );
- pVideoSubMenu->Add( new CMenuItem( _T("640x480"), MENU_640x480 ) );
- pVideoSubMenu->Add( new CMenuItem( _T("800x600"), MENU_800x600 ) );
- pVideoSubMenu->Add( new CMenuItem( _T("1024x768"), MENU_1024x768 ) );
- pVideoSubMenu->Add( new CMenuItem( _T("Back"), MENU_BACK ) );
-
- // Build sound menu
- CMenuItem* pSoundSubMenu = new CMenuItem( _T("Sound Menu"), MENU_SOUND );
- pSoundSubMenu->Add( new CMenuItem( _T("Sound On"), MENU_SOUNDON ) );
- pSoundSubMenu->Add( new CMenuItem( _T("Sound Off"), MENU_SOUNDOFF ) );
- pSoundSubMenu->Add( new CMenuItem( _T("Back"), MENU_BACK ) );
-
- // Build input menu
- CMenuItem* pInputSubMenu = new CMenuItem( _T("Input Menu"), MENU_INPUT );
- pInputSubMenu->Add( new CMenuItem( _T("View Devices"), MENU_VIEWDEVICES ) );
- pInputSubMenu->Add( new CMenuItem( _T("Config Devices"), MENU_CONFIGDEVICES ) );
- pInputSubMenu->Add( new CMenuItem( _T("Back"), MENU_BACK ) );
-
- // Build main menu
- g_pMainMenu = new CMenuItem( _T("Main Menu"), MENU_MAIN );
- g_pMainMenu->Add( pVideoSubMenu );
- g_pMainMenu->Add( pSoundSubMenu );
- g_pMainMenu->Add( pInputSubMenu );
- g_pMainMenu->Add( new CMenuItem( _T("Back to Game"), MENU_BACK ) );
-
- // Build "quit game?" menu
- g_pQuitMenu = new CMenuItem( _T("Quit Game?"), MENU_MAIN );
- g_pQuitMenu->Add( new CMenuItem( _T("Yes"), MENU_QUIT ) );
- g_pQuitMenu->Add( new CMenuItem( _T("No"), MENU_BACK ) );
-
- return;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name:
- // Desc:
- //-----------------------------------------------------------------------------
- VOID DestroyMenus()
- {
- SAFE_DELETE( g_pQuitMenu );
- SAFE_DELETE( g_pMainMenu );
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: UpdateMenus()
- // Desc:
- //-----------------------------------------------------------------------------
- VOID UpdateMenus()
- {
- if( g_pCurrentMenu == NULL )
- return;
-
- // Keep track of current selected menu, to check later for changes
- DWORD dwCurrentSelectedMenu = g_pCurrentMenu->dwSelectedMenu;
-
- // Check for menu up/down input
- if( g_bMenuUp )
- {
- if( g_pCurrentMenu->dwSelectedMenu > 0 )
- g_pCurrentMenu->dwSelectedMenu--;
- }
- else if( g_bMenuDown )
- {
- if( (g_pCurrentMenu->dwSelectedMenu+1) < g_pCurrentMenu->dwNumChildren )
- g_pCurrentMenu->dwSelectedMenu++;
- }
-
- // The the current menu changed, play a sound
- if( dwCurrentSelectedMenu != g_pCurrentMenu->dwSelectedMenu )
- PlaySound( g_pSphereExplodeSound );
-
- if( g_bMenuSelect )
- {
- PlaySound( g_pSphereExplodeSound );
-
- DWORD dwID = g_pCurrentMenu->pChild[g_pCurrentMenu->dwSelectedMenu]->dwID;
-
- switch( dwID )
- {
- case MENU_BACK:
- g_pCurrentMenu = g_pCurrentMenu->pParent;
- break;
-
- case MENU_VIDEO:
- case MENU_SOUND:
- case MENU_INPUT:
- g_pCurrentMenu = g_pCurrentMenu->pChild[g_pCurrentMenu->dwSelectedMenu];
- break;
-
- case MENU_WINDOWED:
- SwitchDisplayModes( FALSE, 0L, 0L );
- g_pCurrentMenu = NULL;
- break;
-
- case MENU_640x480:
- SwitchDisplayModes( TRUE, 640, 480 );
- g_pCurrentMenu = NULL;
- break;
-
- case MENU_800x600:
- SwitchDisplayModes( TRUE, 800, 600 );
- g_pCurrentMenu = NULL;
- break;
-
- case MENU_1024x768:
- SwitchDisplayModes( TRUE, 1024, 768 );
- g_pCurrentMenu = NULL;
- break;
-
- case MENU_SOUNDON:
- if( g_pMusicManager == NULL )
- CreateSoundObjects( g_hWndMain );
- g_pCurrentMenu = NULL;
- break;
-
- case MENU_SOUNDOFF:
- if( g_pMusicManager )
- DestroySoundObjects();
- g_pCurrentMenu = NULL;
- break;
-
- case MENU_VIEWDEVICES:
- // Put action format to game play actions
- g_pInputDeviceManager->SetActionFormat( g_diafGame, TRUE );
-
- g_bMouseVisible = TRUE;
-
- // Configure the devices (with view capability only)
- if( g_bFullScreen )
- g_pInputDeviceManager->ConfigureDevices( g_hWndMain,
- g_pConfigSurface,
- (VOID*)ConfigureInputDevicesCB,
- DICD_DEFAULT );
- else
- g_pInputDeviceManager->ConfigureDevices( g_hWndMain, NULL, NULL,
- DICD_DEFAULT );
- g_bMouseVisible = FALSE;
-
- g_pCurrentMenu = NULL;
- break;
-
- case MENU_CONFIGDEVICES:
- // Put action format to game play actions
- g_pInputDeviceManager->SetActionFormat( g_diafGame, TRUE );
-
- g_bMouseVisible = TRUE;
-
- // Configure the devices (with edit capability)
- if( g_bFullScreen )
- g_pInputDeviceManager->ConfigureDevices( g_hWndMain,
- g_pConfigSurface,
- (VOID*)ConfigureInputDevicesCB,
- DICD_EDIT );
- else
- g_pInputDeviceManager->ConfigureDevices( g_hWndMain, NULL, NULL,
- DICD_EDIT );
- g_bMouseVisible = FALSE;
-
- g_pCurrentMenu = NULL;
- break;
-
- case MENU_QUIT:
- PostMessage( g_hWndMain, WM_CLOSE, 0, 0 );
- g_pCurrentMenu = NULL;
- break;
- }
- }
-
- // Check if the menu system is being exitted
- if( g_bMenuQuit )
- g_pCurrentMenu = NULL;
-
- // If the menu is going away, go back to game play actions
- if( g_pCurrentMenu == NULL )
- g_pInputDeviceManager->SetActionFormat( g_diafGame, TRUE );
-
- // Clear menu inputs
- g_bMenuUp = FALSE;
- g_bMenuDown = FALSE;
- g_bMenuSelect = FALSE;
- g_bMenuQuit = FALSE;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Display support code (using Direct3D functionality from D3DUtil.h)
- //-----------------------------------------------------------------------------
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: CreateDisplayObjects()
- // Desc:
- //-----------------------------------------------------------------------------
- HRESULT CreateDisplayObjects( HWND hWnd )
- {
- HRESULT hr, hr1, hr2;
-
- // Construct a new display
- LPDIRECT3D8 pD3D = Direct3DCreate8( D3D_SDK_VERSION );
- if( NULL == pD3D )
- {
- CleanupAndDisplayError( DONUTS3DERR_NODIRECT3D );
- return E_FAIL;
- }
-
- // Get the current desktop format
- pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &g_DesktopMode );
-
- const D3DFORMAT fmtFullscreenArray[] =
- {
- D3DFMT_R5G6B5,
- D3DFMT_X1R5G5B5,
- D3DFMT_A1R5G5B5,
- D3DFMT_X8R8G8B8,
- D3DFMT_A8R8G8B8,
- };
- const INT numFullscreenFmts = sizeof(fmtFullscreenArray) / sizeof(fmtFullscreenArray[0]);
- INT iFmt;
-
- // Find a pixel format that will be good for fullscreen back buffers
- for( iFmt = 0; iFmt < numFullscreenFmts; iFmt++ )
- {
- if( SUCCEEDED( pD3D->CheckDeviceType( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
- fmtFullscreenArray[iFmt], fmtFullscreenArray[iFmt], FALSE ) ) )
- {
- g_d3dfmtFullscreen = fmtFullscreenArray[iFmt];
- break;
- }
- }
-
- const D3DFORMAT fmtTextureArray[] =
- {
- D3DFMT_A1R5G5B5,
- D3DFMT_A4R4G4B4,
- D3DFMT_A8R8G8B8,
- };
- const INT numTextureFmts = sizeof(fmtTextureArray) / sizeof(fmtTextureArray[0]);
-
- // Find a format that is supported as a texture map for the current mode
- for( iFmt = 0; iFmt < numTextureFmts; iFmt++ )
- {
- if( SUCCEEDED( pD3D->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
- g_DesktopMode.Format, 0, D3DRTYPE_TEXTURE, fmtTextureArray[iFmt] ) ) )
- {
- g_d3dfmtTexture = fmtTextureArray[iFmt];
- break;
- }
- }
-
- // Set up presentation parameters for the display
- ZeroMemory( &g_d3dpp, sizeof(g_d3dpp) );
- g_d3dpp.Windowed = !g_bFullScreen;
- g_d3dpp.BackBufferCount = 1;
- g_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
- g_d3dpp.EnableAutoDepthStencil = TRUE;
- g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
- if( g_bFullScreen )
- {
- g_d3dpp.hDeviceWindow = hWnd;
- g_d3dpp.BackBufferWidth = g_dwScreenWidth;
- g_d3dpp.BackBufferHeight = g_dwScreenHeight;
- g_d3dpp.BackBufferFormat = g_d3dfmtFullscreen;
- }
- else
- {
- g_d3dpp.BackBufferFormat = g_DesktopMode.Format;
- }
-
- // Create the device
- hr = pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
- D3DCREATE_SOFTWARE_VERTEXPROCESSING,
- &g_d3dpp, &g_pd3dDevice );
- pD3D->Release();
- if( FAILED(hr) )
- {
- CleanupAndDisplayError( DONUTS3DERR_NOD3DDEVICE );
- return E_FAIL;
- }
-
- // Create some game fonts
- g_pGameFont = new CD3DFont( _T("Tahoma"), 30, 0L );
- g_pGameFont->InitDeviceObjects( g_pd3dDevice );
-
- g_pMenuFont = new CD3DFont( _T("Impact"), 48, 0L );
- g_pMenuFont->InitDeviceObjects( g_pd3dDevice );
-
- // Find the media files (textures and geometry models) for the game
- TCHAR strGameTexture1[512];
- TCHAR strGameTexture2[512];
- hr1 = DXUtil_FindMediaFile( strGameTexture1, _T("Donuts1.bmp") );
- hr2 = DXUtil_FindMediaFile( strGameTexture2, _T("Donuts2.bmp") );
-
- if( FAILED(hr1) || FAILED(hr2) )
- {
- CleanupAndDisplayError( DONUTS3DERR_NOTEXTURES );
- return E_FAIL;
- }
-
- // Load the game textures
- if( FAILED( D3DUtil_CreateTexture( g_pd3dDevice, strGameTexture1,
- &g_pGameTexture1, g_d3dfmtTexture ) ) ||
- FAILED( D3DUtil_CreateTexture( g_pd3dDevice, strGameTexture2,
- &g_pGameTexture2, g_d3dfmtTexture ) ) )
- {
- CleanupAndDisplayError( DONUTS3DERR_NOTEXTURES );
- return E_FAIL;
- }
-
- D3DUtil_SetColorKey( g_pGameTexture1, 0x00000000 );
- D3DUtil_SetColorKey( g_pGameTexture2, 0x00000000 );
-
- // Load the geometry models
- hr1 = LoadShipModel();
- hr2 = LoadTerrainModel();
-
- if( FAILED(hr1) || FAILED(hr2) )
- {
- CleanupAndDisplayError( DONUTS3DERR_NOGEOMETRY );
- return E_FAIL;
- }
-
- // Create a viewport covering sqaure
- if( FAILED( g_pd3dDevice->CreateVertexBuffer( 4*sizeof(SCREENVERTEX),
- D3DUSAGE_WRITEONLY, D3DFVF_SCREENVERTEX,
- D3DPOOL_MANAGED, &g_pViewportVB ) ) )
- {
- CleanupAndDisplayError( DONUTS3DERR_NO3DRESOURCES );
- return E_FAIL;
- }
-
- // Create a sqaure for rendering the sprites
- if( FAILED( g_pd3dDevice->CreateVertexBuffer( 4*sizeof(SPRITEVERTEX),
- D3DUSAGE_WRITEONLY, D3DFVF_SPRITEVERTEX,
- D3DPOOL_MANAGED, &g_pSpriteVB ) ) )
- {
- CleanupAndDisplayError( DONUTS3DERR_NO3DRESOURCES );
- return E_FAIL;
- }
-
- // Now that all the display objects are created, "restore" them (create
- // local mem objects and set state)
- if( FAILED( RestoreDisplayObjects() ) )
- return E_FAIL;
-
- // The display is now ready
- g_bDisplayReady = TRUE;
- return S_OK;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: RestoreDisplayObjects()
- // Desc:
- //-----------------------------------------------------------------------------
- HRESULT RestoreDisplayObjects()
- {
- HRESULT hr;
- HWND hWnd = g_hWndMain;
-
- if( FALSE == g_bFullScreen )
- {
- // If we are still a WS_POPUP window we should convert to a normal app
- // window so we look like a windows app.
- DWORD dwStyle = GetWindowStyle( hWnd );
- dwStyle &= ~WS_POPUP;
- dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX;
- SetWindowLong( hWnd, GWL_STYLE, dwStyle );
-
- // Aet window size
- RECT rc;
- SetRect( &rc, 0, 0, 640, 480 );
-
- AdjustWindowRectEx( &rc, GetWindowStyle(hWnd), GetMenu(hWnd) != NULL,
- GetWindowExStyle(hWnd) );
-
- SetWindowPos( hWnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top,
- SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
-
- SetWindowPos( hWnd, HWND_NOTOPMOST, 0, 0, 0, 0,
- SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
-
- // Make sure our window does not hang outside of the work area
- RECT rcWork;
- SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWork, 0 );
- GetWindowRect( hWnd, &rc );
- if( rc.left < rcWork.left ) rc.left = rcWork.left;
- if( rc.top < rcWork.top ) rc.top = rcWork.top;
- SetWindowPos( hWnd, NULL, rc.left, rc.top, 0, 0,
- SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
- }
-
- // Create the device-dependent objects for the file-based mesh objects
- g_pShipFileObject->RestoreDeviceObjects( g_pd3dDevice );
- g_pTerrain->RestoreDeviceObjects( g_pd3dDevice );
- g_pGameFont->RestoreDeviceObjects();
- g_pMenuFont->RestoreDeviceObjects();
-
- // Get viewport dimensions
- D3DVIEWPORT8 vp;
- g_pd3dDevice->GetViewport(&vp);
- FLOAT sx = (FLOAT)vp.Width;
- FLOAT sy = (FLOAT)vp.Height;
-
- // Setup dimensions for the viewport covering sqaure
- SCREENVERTEX* v;
- g_pViewportVB->Lock( 0, 0, (BYTE**)&v, 0 );
- v[0].p = D3DXVECTOR4( 0,sy,0.0f,1.0f);
- v[1].p = D3DXVECTOR4( 0, 0,0.0f,1.0f);
- v[2].p = D3DXVECTOR4(sx,sy,0.0f,1.0f);
- v[3].p = D3DXVECTOR4(sx, 0,0.0f,1.0f);
- g_pViewportVB->Unlock();
-
- // Create a surface for confguring DInput devices
- hr = g_pd3dDevice->CreateImageSurface( 640, 480, g_d3dfmtFullscreen, &g_pConfigSurface );
- if( FAILED(hr) )
- {
- CleanupAndDisplayError( DONUTS3DERR_NO3DRESOURCES );
- return E_FAIL;
- }
-
- // Set up the camera
- g_Camera.SetViewParams( D3DXVECTOR3(0.0f,0.0f,0.0f), D3DXVECTOR3(0.0f,0.0f,1.0f),
- D3DXVECTOR3(0.0f,1.0f,0.0f) );
- g_Camera.SetProjParams( D3DX_PI/4, 1.0f, 0.1f, 100.0f );
-
- // Set up default matrices (using the CD3DCamera class)
- g_pd3dDevice->SetTransform( D3DTS_VIEW, &g_Camera.GetViewMatrix() );
- g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &g_Camera.GetProjMatrix() );
-
- // Setup a material
- D3DMATERIAL8 mtrl;
- D3DUtil_InitMaterial( mtrl, 1.0f, 1.0f, 1.0f );
- g_pd3dDevice->SetMaterial( &mtrl );
-
- // Set up lighting states
- D3DLIGHT8 light;
- D3DUtil_InitLight( light, D3DLIGHT_DIRECTIONAL, 1.0f, -1.0f, 1.0f );
- g_pd3dDevice->SetLight( 0, &light );
- g_pd3dDevice->LightEnable( 0, TRUE );
-
- g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
- g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x33333333 );
-
- // Set miscellaneous render states
- g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
- g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
- g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
- g_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_POINT );
- g_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_POINT );
- g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
-
- return S_OK;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: InvalidateDisplayObjects()
- // Desc:
- //-----------------------------------------------------------------------------
- HRESULT InvalidateDisplayObjects()
- {
- g_pShipFileObject->InvalidateDeviceObjects();
- g_pTerrain->InvalidateDeviceObjects();
- g_pGameFont->InvalidateDeviceObjects();
- g_pMenuFont->InvalidateDeviceObjects();
-
- SAFE_RELEASE( g_pConfigSurface );
-
- return S_OK;
- }
-
-
-
- //-----------------------------------------------------------------------------
- // Name: DestroyDisplayObjects()
- // Desc:
- //-----------------------------------------------------------------------------
- HRESULT DestroyDisplayObjects()
- {
- DisplayObject* pDO;
- while( g_pDisplayList != NULL )
- {
- pDO = g_pDisplayList;
- g_pDisplayList = g_pDisplayList->pNext;
- delete pDO;
- if( g_pDisplayList != NULL)
- g_pDisplayList->pPrev = NULL;
- }
-
- SAFE_RELEASE( g_pGameTexture1 );
- SAFE_RELEASE( g_pGameTexture2 );
-
- SAFE_DELETE( g_pGameFont );
- SAFE_DELETE( g_pMenuFont );
-
- SAFE_RELEASE( g_pConfigSurface );
-
- if( g_pShipFileObject != NULL )
- g_pShipFileObject->Destroy();
- if( g_pTerrain != NULL )
- g_pTerrain->Destroy();
-
- SAFE_DELETE( g_pTerrain );
- SAFE_DELETE( g_pShipFileObject );
-
- SAFE_RELEASE( g_pViewportVB );
- SAFE_RELEASE( g_pSpriteVB );
- SAFE_RELEASE( g_pd3dDevice );
-
- return S_OK;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: SwitchDisplayModes()
- // Desc:
- //-----------------------------------------------------------------------------
- HRESULT SwitchDisplayModes( BOOL bFullScreen, DWORD dwWidth, DWORD dwHeight )
- {
- HRESULT hr;
-
- if( FALSE==g_bIsActive || FALSE==g_bDisplayReady )
- return S_OK;
-
- // Check to see if a change was actually requested
- if( bFullScreen )
- {
- if( g_dwScreenWidth==dwWidth && g_dwScreenHeight==dwHeight &&
- g_bFullScreen==bFullScreen )
- return S_OK;
- }
- else
- {
- if( g_bFullScreen == FALSE )
- return S_OK;
- }
-
- // Invalidate the old display objects
- g_bDisplayReady = FALSE;
- InvalidateDisplayObjects();
-
- // Set up the new presentation paramters
- if( bFullScreen )
- {
- g_d3dpp.Windowed = FALSE;
- g_d3dpp.hDeviceWindow = g_hWndMain;
- g_d3dpp.BackBufferWidth = g_dwScreenWidth = dwWidth;
- g_d3dpp.BackBufferHeight = g_dwScreenHeight = dwHeight;
- g_d3dpp.BackBufferFormat = g_d3dfmtFullscreen;
- }
- else
- {
- g_d3dpp.Windowed = TRUE;
- g_d3dpp.hDeviceWindow = NULL;
- g_d3dpp.BackBufferWidth = 0L;
- g_d3dpp.BackBufferHeight = 0L;
-
- g_d3dpp.BackBufferFormat = g_DesktopMode.Format;
- }
-
- // Reset the device
- if( SUCCEEDED( hr = g_pd3dDevice->Reset( &g_d3dpp ) ) )
- {
- g_bFullScreen = bFullScreen;
- if( SUCCEEDED( hr = RestoreDisplayObjects() ) )
- {
- g_bDisplayReady = TRUE;
- return S_OK;
- }
- }
-
- // If we get here, a fatal error occurred
- PostMessage( g_hWndMain, WM_CLOSE, 0, 0 );
- return E_FAIL;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: ShowFrame()
- // Desc:
- //-----------------------------------------------------------------------------
- VOID ShowFrame()
- {
- if( NULL == g_pd3dDevice )
- return;
-
- // Present the backbuffer contents to the front buffer
- g_pd3dDevice->Present( 0, 0, 0, 0 );
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Sound support code (using DMusic functionality from DMUtil.h)
- //-----------------------------------------------------------------------------
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: CreateSoundObjects()
- // Desc:
- //-----------------------------------------------------------------------------
- HRESULT CreateSoundObjects( HWND hWnd )
- {
- // Create the music manager class, used to create the sounds
- g_pMusicManager = new CMusicManager();
- if( FAILED( g_pMusicManager->Initialize( hWnd ) ) )
- return E_FAIL;
-
- // Instruct the music manager where to find the files
- g_pMusicManager->SetSearchDirectory( DXUtil_GetDXSDKMediaPath() );
-
- // Create the sounds
- g_pMusicManager->CreateSegmentFromResource( &g_pBeginLevelSound, _T("BEGINLEVEL"), _T("WAV") );
- g_pMusicManager->CreateSegmentFromResource( &g_pEngineIdleSound, _T("ENGINEIDLE") , _T("WAV"));
- g_pMusicManager->CreateSegmentFromResource( &g_pEngineRevSound, _T("ENGINEREV") , _T("WAV"));
- g_pMusicManager->CreateSegmentFromResource( &g_pShieldBuzzSound, _T("SHIELDBUZZ") , _T("WAV"));
- g_pMusicManager->CreateSegmentFromResource( &g_pShipExplodeSound, _T("SHIPEXPLODE") , _T("WAV"));
- g_pMusicManager->CreateSegmentFromResource( &g_pFireBulletSound, _T("GUNFIRE") , _T("WAV"));
- g_pMusicManager->CreateSegmentFromResource( &g_pShipBounceSound, _T("SHIPBOUNCE") , _T("WAV"));
- g_pMusicManager->CreateSegmentFromResource( &g_pDonutExplodeSound, _T("DONUTEXPLODE") , _T("WAV"));
- g_pMusicManager->CreateSegmentFromResource( &g_pPyramidExplodeSound, _T("PYRAMIDEXPLODE") , _T("WAV"));
- g_pMusicManager->CreateSegmentFromResource( &g_pCubeExplodeSound, _T("CUBEEXPLODE") , _T("WAV"));
- g_pMusicManager->CreateSegmentFromResource( &g_pSphereExplodeSound, _T("SPHEREEXPLODE") , _T("WAV"));
-
- return S_OK;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: DestroySoundObjects()
- // Desc:
- //-----------------------------------------------------------------------------
- VOID DestroySoundObjects()
- {
- SAFE_DELETE( g_pBeginLevelSound );
- SAFE_DELETE( g_pEngineIdleSound );
- SAFE_DELETE( g_pEngineRevSound );
- SAFE_DELETE( g_pShieldBuzzSound );
- SAFE_DELETE( g_pShipExplodeSound );
- SAFE_DELETE( g_pFireBulletSound );
- SAFE_DELETE( g_pShipBounceSound );
- SAFE_DELETE( g_pDonutExplodeSound );
- SAFE_DELETE( g_pPyramidExplodeSound );
- SAFE_DELETE( g_pCubeExplodeSound );
- SAFE_DELETE( g_pSphereExplodeSound );
-
- SAFE_DELETE( g_pMusicManager );
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Input support code (using DInput functionality from DIUtil.h)
- //-----------------------------------------------------------------------------
-
-
-
- //-----------------------------------------------------------------------------
- // Name: CreateInputObjects()
- // Desc:
- //-----------------------------------------------------------------------------
- HRESULT CreateInputObjects( HWND hWnd )
- {
- HRESULT hr;
-
- // Setup action format for the acutal gameplay
- ZeroMemory( &g_diafGame, sizeof(DIACTIONFORMAT) );
- g_diafGame.dwSize = sizeof(DIACTIONFORMAT);
- g_diafGame.dwActionSize = sizeof(DIACTION);
- g_diafGame.dwDataSize = NUMBER_OF_GAMEACTIONS * sizeof(DWORD);
- g_diafGame.guidActionMap = g_AppGuid;
- g_diafGame.dwGenre = DIVIRTUAL_SPACESIM;
- g_diafGame.dwNumActions = NUMBER_OF_GAMEACTIONS;
- g_diafGame.rgoAction = g_rgGameAction;
- g_diafGame.lAxisMin = -10;
- g_diafGame.lAxisMax = 10;
- g_diafGame.dwBufferSize = 16;
- _tcscpy( g_diafGame.tszActionMap, _T("Donuts3D New") );
-
- // Setup action format for the in-game menus
- ZeroMemory( &g_diafBrowser, sizeof(DIACTIONFORMAT) );
- g_diafBrowser.dwSize = sizeof(DIACTIONFORMAT);
- g_diafBrowser.dwActionSize = sizeof(DIACTION);
- g_diafBrowser.dwDataSize = NUMBER_OF_BROWSERACTIONS * sizeof(DWORD);
- g_diafBrowser.guidActionMap = g_AppGuid;
- g_diafBrowser.dwGenre = DIVIRTUAL_BROWSER_CONTROL;
- g_diafBrowser.dwNumActions = NUMBER_OF_BROWSERACTIONS;
- g_diafBrowser.rgoAction = g_rgBrowserAction;
- g_diafBrowser.lAxisMin = -10;
- g_diafBrowser.lAxisMax = 10;
- g_diafBrowser.dwBufferSize = 16;
- _tcscpy( g_diafBrowser.tszActionMap, _T("Donuts New") );
-
- // Create a new input device manager
- g_pInputDeviceManager = new CInputDeviceManager();
-
- if( FAILED( hr = g_pInputDeviceManager->Create( hWnd, NULL, g_diafGame ) ) )
- {
- CleanupAndDisplayError( DONUTS3DERR_NOINPUT );
- return E_FAIL;
- }
-
- return S_OK;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: DestroyInputObjects()
- // Desc:
- //-----------------------------------------------------------------------------
- VOID DestroyInputObjects()
- {
- // Delete input device manager
- SAFE_DELETE( g_pInputDeviceManager );
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: ConfigureInputDevicesCB()
- // Desc: Callback function for configuring input devices. This function is
- // called in fullscreen modes, so that the input device configuration
- // window can update the screen.
- //-----------------------------------------------------------------------------
- BOOL CALLBACK ConfigureInputDevicesCB( IUnknown* pUnknown, VOID* pUserData )
- {
- if( g_dwAppState != APPSTATE_ACTIVE )
- return TRUE;
-
- // Get access to the surface
- LPDIRECT3DSURFACE8 pConfigSurface;
- if( FAILED( pUnknown->QueryInterface( IID_IDirect3DSurface8,
- (VOID**)&pConfigSurface ) ) )
- return TRUE;
-
- // Draw the scene, with the config surface blitted on top
- DrawDisplayList();
-
- RECT rcSrc;
- SetRect( &rcSrc, 0, 0, 640, 480 );
-
- POINT ptDst;
- ptDst.x = (g_dwScreenWidth-640)/2;
- ptDst.y = (g_dwScreenHeight-480)/2;
-
- LPDIRECT3DSURFACE8 pBackBuffer;
- g_pd3dDevice->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer );
- g_pd3dDevice->CopyRects( pConfigSurface, &rcSrc, 1, pBackBuffer, &ptDst );
- pBackBuffer->Release();
-
- ShowFrame();
-
- // Release the surface
- pConfigSurface->Release();
-
- return TRUE;
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: GetInput()
- // Desc: Processes data from the input device. Uses GetDeviceState().
- //-----------------------------------------------------------------------------
- VOID GetInput()
- {
- // Buffers for accumulating data from input devices
- static FLOAT fLeftThrust[10] = {0};
- static FLOAT fRightThrust[10] = {0};
- static FLOAT fForwardThrust[10] = {0};
- static FLOAT fReverseThrust[10] = {0};
-
- // Get access to the list of semantically-mapped input devices
- LPDIRECTINPUTDEVICE8* pdidDevices;
- DWORD dwNumDevices;
- g_pInputDeviceManager->GetDevices( &pdidDevices, &dwNumDevices );
-
- // Loop through all devices and check game input
- for( DWORD i=0; i<dwNumDevices; i++ )
- {
- DIDEVICEOBJECTDATA rgdod[10];
- DWORD dwItems = 10;
- HRESULT hr;
-
- hr = pdidDevices[i]->Acquire();
- hr = pdidDevices[i]->Poll();
- hr = pdidDevices[i]->GetDeviceData( sizeof(DIDEVICEOBJECTDATA),
- rgdod, &dwItems, 0 );
- if( FAILED(hr) )
- continue;
-
- // Get the sematics codes for the game menu
- for( DWORD j=0; j<dwItems; j++ )
- {
- BOOL bButtonState = (rgdod[j].dwData==0x80) ? TRUE : FALSE;
- FLOAT fButtonState = (rgdod[j].dwData==0x80) ? 1.0f : 0.0f;
- FLOAT fAxisState = (FLOAT)((int)rgdod[j].dwData)/10.0f;
-
- switch( rgdod[j].uAppData )
- {
- // Handle semantics for the game menu
- case INPUT_MENU_LR: // There are no nieghboring menus so ignore this one
- break;
-
- case INPUT_MENU_UD:
- {
- // The axis goes between -1 and 1. We need to set g_bMenuDown or g_bMenuUp
- // only one time.
- static BOOL s_bOneTimeUD = FALSE;
-
- if( fabs(fAxisState) < 0.2 )
- {
- s_bOneTimeUD = FALSE;
- }
- else
- {
- if ( !s_bOneTimeUD )
- {
- if( fAxisState > 0.0f )
- g_bMenuDown = TRUE;
- else
- g_bMenuUp = TRUE;
-
- s_bOneTimeUD = TRUE;
- }
- }
-
- break;
- }
-
- case INPUT_MENU_UP: g_bMenuUp |= bButtonState; break;
- case INPUT_MENU_DOWN: g_bMenuDown |= bButtonState; break;
- case INPUT_MENU_LEFT: g_bMenuLeft |= bButtonState; break;
- case INPUT_MENU_RIGHT: g_bMenuRight |= bButtonState; break;
- case INPUT_MENU_SELECT: g_bMenuSelect |= bButtonState; break;
- case INPUT_MENU_QUIT: g_bMenuQuit |= bButtonState; break;
-
- case INPUT_MENU_WHEEL:
- if( fAxisState > 0.0f )
- g_bMenuUp = TRUE;
- else
- g_bMenuDown = TRUE;
- break;
-
- // Handle semantics for normal game play
- case INPUT_AXIS_LR:
- case INPUT_MOUSE_LR:
- fLeftThrust[i] = 0.0f;
- fRightThrust[i] = 0.0f;
- if( fAxisState > 0.0f )
- fRightThrust[i] = +fAxisState;
- else
- fLeftThrust[i] = -fAxisState;
- break;
- case INPUT_AXIS_UD:
- case INPUT_MOUSE_UD:
- fForwardThrust[i] = 0.0f;
- fReverseThrust[i] = 0.0f;
- if( fAxisState > 0.0f )
- fReverseThrust[i] = +fAxisState;
- else
- fForwardThrust[i] = -fAxisState;
- break;
-
- // User wants to change ship type
- case INPUT_AXIS_SHIPTYPE:
- case INPUT_MOUSE_SHIPTYPE:
- SwitchModel();
- break;
-
- case INPUT_TURNLEFT: fLeftThrust[i] = fButtonState; break;
- case INPUT_TURNRIGHT: fRightThrust[i] = fButtonState; break;
- case INPUT_FORWARDTHRUST: fForwardThrust[i] = fButtonState; break;
- case INPUT_REVERSETHRUST: fReverseThrust[i] = fButtonState; break;
-
- case INPUT_FIREWEAPONS: g_bFiringWeapons = bButtonState; break;
- case INPUT_CHANGEVIEW: g_bChangeView = bButtonState; break;
-
- // User wants to change weapons
- case INPUT_CHANGEWEAPONS:
- if( bButtonState )
- {
- if( ++g_dwBulletType > 3 )
- g_dwBulletType = 0L;
- }
- break;
-
- // User wants to change ship type
- case INPUT_CHANGESHIPTYPE:
- if( bButtonState )
- SwitchModel();
- break;
-
- case INPUT_START:
- if( bButtonState )
- g_bPaused = !g_bPaused;
- break;
-
- case INPUT_DISPLAYGAMEMENU:
- if( bButtonState )
- {
- PlaySound( g_pSphereExplodeSound );
- g_pCurrentMenu = g_pMainMenu;
- g_pInputDeviceManager->SetActionFormat( g_diafBrowser, FALSE );
- }
- break;
-
- case INPUT_QUITGAME:
- if( bButtonState )
- {
- PlaySound( g_pSphereExplodeSound );
- g_pCurrentMenu = g_pQuitMenu;
- g_pInputDeviceManager->SetActionFormat( g_diafBrowser, FALSE );
- }
- break;
- }
- }
- }
-
- if( g_pShip->bVisible )
- {
- // Accumulate thrust inputs
- g_fBank = 0.0f;
- g_fThrust = 0.0f;
-
- for( DWORD i=0; i<dwNumDevices; i++ )
- {
- if( fRightThrust[i] > 0.4f ) g_fBank += fRightThrust[i];
- if( fLeftThrust[i] > 0.4f ) g_fBank -= fLeftThrust[i];
-
- if( fForwardThrust[i] > 0.4f ) g_fThrust += fForwardThrust[i];
- if( fReverseThrust[i] > 0.4f ) g_fThrust -= fReverseThrust[i];
- }
- }
- else
- {
- // If the ship is not visible, zero out appropriate inputs
- g_fBank = 0.0f;
- g_fThrust = 0.0f;
- g_bFiringWeapons = FALSE;
- g_bChangeView = FALSE;
- }
- }
-
-
-
-
- //-----------------------------------------------------------------------------
- // Error handling
- //-----------------------------------------------------------------------------
-
-
-
-
- //-----------------------------------------------------------------------------
- // Name: CleanupAndDisplayError()
- // Desc:
- //-----------------------------------------------------------------------------
- VOID CleanupAndDisplayError( DWORD dwError )
- {
- TCHAR* strDbgOut;
- TCHAR* strMsgBox;
-
- // Cleanup the app
- DestroyGameObjects();
-
- // Make the cursor visible
- SetCursor( LoadCursor( NULL, IDC_ARROW ) );
- g_bMouseVisible = TRUE;
-
- // Get the appropriate error strings
- switch( dwError )
- {
- case DONUTS3DERR_NODIRECT3D:
- strDbgOut = _T("Could not create Direct3D\n");
- strMsgBox = _T("Could not create Direct3D.\n\n")
- _T("Please make sure you have the latest DirectX\n")
- _T(".dlls installed on your system.");
- break;
- case DONUTS3DERR_NOD3DDEVICE:
- strDbgOut = _T("Could not create a Direct3D device\n");
- strMsgBox = _T("Could not create a Direct3D device. Your\n")
- _T("graphics accelerator is not sufficient to\n")
- _T("run this demo, or your desktop is using\n")
- _T("a color format that cannot be accelerated by\n")
- _T("your graphics card (try 16-bit mode).");
- break;
- case DONUTS3DERR_NOTEXTURES:
- strDbgOut = _T("Could not load textures\n");
- strMsgBox = _T("Couldn't load game textures.\n\n")
- _T("Either your graphics hardware does not have\n")
- _T("sufficient resources, or the DirectX SDK was\n")
- _T("not properly installed.");
- break;
- case DONUTS3DERR_NOGEOMETRY:
- strDbgOut = _T("Could not load .x models\n");
- strMsgBox = _T("Couldn't load game geometry.\n\n")
- _T("Either your graphics hardware does not have\n")
- _T("sufficient resources, or the DirectX SDK was\n")
- _T("not properly installed.");
- break;
- case DONUTS3DERR_NO3DRESOURCES:
- strDbgOut = _T("Couldn't load create a d3d object\n");
- strMsgBox = _T("Couldn't create display objects.\n")
- _T("Yourr graphics hardware does not have\n")
- _T("sufficient resources to run this app.");
- break;
- case DONUTS3DERR_NOINPUT:
- strDbgOut = _T("Could not create input objects\n");
- strMsgBox = _T("Could not create input objects.");
- break;
- }
-
- // Output the error strings
- OutputDebugString( strDbgOut );
- MessageBox( g_hWndMain, strMsgBox, _T("Donuts3D"), MB_OK );
- }
-
-